Initial Commit
This commit is contained in:
1 parent
377b32db6e
commit
2d9a5eecba
14134 files changed
+1160982
No files matched your search
+167
@@ -0,0 +1,167 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.ListBuilder;
|
||||
import com.mojang.serialization.MapLike;
|
||||
import com.mojang.serialization.RecordBuilder;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A {@link DynamicOps} that delegates all functionality to an internal delegate. Comments and parameters here are
|
||||
* copied from {@link DynamicOps} in DataFixerUpper.
|
||||
*/
|
||||
public abstract class DelegatingOps<T> implements DynamicOps<T> {
|
||||
protected final DynamicOps<T> delegate;
|
||||
|
||||
protected DelegatingOps(DynamicOps<T> pDelegate) {
|
||||
this.delegate = pDelegate;
|
||||
}
|
||||
|
||||
public T empty() {
|
||||
return this.delegate.empty();
|
||||
}
|
||||
|
||||
public <U> U convertTo(DynamicOps<U> pOutOps, T pInput) {
|
||||
return this.delegate.convertTo(pOutOps, pInput);
|
||||
}
|
||||
|
||||
public DataResult<Number> getNumberValue(T pInput) {
|
||||
return this.delegate.getNumberValue(pInput);
|
||||
}
|
||||
|
||||
public T createNumeric(Number pI) {
|
||||
return this.delegate.createNumeric(pI);
|
||||
}
|
||||
|
||||
public T createByte(byte pValue) {
|
||||
return this.delegate.createByte(pValue);
|
||||
}
|
||||
|
||||
public T createShort(short pValue) {
|
||||
return this.delegate.createShort(pValue);
|
||||
}
|
||||
|
||||
public T createInt(int pValue) {
|
||||
return this.delegate.createInt(pValue);
|
||||
}
|
||||
|
||||
public T createLong(long pValue) {
|
||||
return this.delegate.createLong(pValue);
|
||||
}
|
||||
|
||||
public T createFloat(float pValue) {
|
||||
return this.delegate.createFloat(pValue);
|
||||
}
|
||||
|
||||
public T createDouble(double pValue) {
|
||||
return this.delegate.createDouble(pValue);
|
||||
}
|
||||
|
||||
public DataResult<Boolean> getBooleanValue(T pInput) {
|
||||
return this.delegate.getBooleanValue(pInput);
|
||||
}
|
||||
|
||||
public T createBoolean(boolean pValue) {
|
||||
return this.delegate.createBoolean(pValue);
|
||||
}
|
||||
|
||||
public DataResult<String> getStringValue(T pInput) {
|
||||
return this.delegate.getStringValue(pInput);
|
||||
}
|
||||
|
||||
public T createString(String pValue) {
|
||||
return this.delegate.createString(pValue);
|
||||
}
|
||||
|
||||
public DataResult<T> mergeToList(T pList, T pValue) {
|
||||
return this.delegate.mergeToList(pList, pValue);
|
||||
}
|
||||
|
||||
public DataResult<T> mergeToList(T pList, List<T> pValues) {
|
||||
return this.delegate.mergeToList(pList, pValues);
|
||||
}
|
||||
|
||||
public DataResult<T> mergeToMap(T pMap, T pKey, T pValue) {
|
||||
return this.delegate.mergeToMap(pMap, pKey, pValue);
|
||||
}
|
||||
|
||||
public DataResult<T> mergeToMap(T pMap, MapLike<T> pValues) {
|
||||
return this.delegate.mergeToMap(pMap, pValues);
|
||||
}
|
||||
|
||||
public DataResult<Stream<Pair<T, T>>> getMapValues(T pInput) {
|
||||
return this.delegate.getMapValues(pInput);
|
||||
}
|
||||
|
||||
public DataResult<Consumer<BiConsumer<T, T>>> getMapEntries(T pInput) {
|
||||
return this.delegate.getMapEntries(pInput);
|
||||
}
|
||||
|
||||
public T createMap(Stream<Pair<T, T>> pMap) {
|
||||
return this.delegate.createMap(pMap);
|
||||
}
|
||||
|
||||
public DataResult<MapLike<T>> getMap(T pInput) {
|
||||
return this.delegate.getMap(pInput);
|
||||
}
|
||||
|
||||
public DataResult<Stream<T>> getStream(T pInput) {
|
||||
return this.delegate.getStream(pInput);
|
||||
}
|
||||
|
||||
public DataResult<Consumer<Consumer<T>>> getList(T pInput) {
|
||||
return this.delegate.getList(pInput);
|
||||
}
|
||||
|
||||
public T createList(Stream<T> pInput) {
|
||||
return this.delegate.createList(pInput);
|
||||
}
|
||||
|
||||
public DataResult<ByteBuffer> getByteBuffer(T pInput) {
|
||||
return this.delegate.getByteBuffer(pInput);
|
||||
}
|
||||
|
||||
public T createByteList(ByteBuffer pInput) {
|
||||
return this.delegate.createByteList(pInput);
|
||||
}
|
||||
|
||||
public DataResult<IntStream> getIntStream(T pInput) {
|
||||
return this.delegate.getIntStream(pInput);
|
||||
}
|
||||
|
||||
public T createIntList(IntStream pInput) {
|
||||
return this.delegate.createIntList(pInput);
|
||||
}
|
||||
|
||||
public DataResult<LongStream> getLongStream(T pInput) {
|
||||
return this.delegate.getLongStream(pInput);
|
||||
}
|
||||
|
||||
public T createLongList(LongStream pInput) {
|
||||
return this.delegate.createLongList(pInput);
|
||||
}
|
||||
|
||||
public T remove(T pInput, String pKey) {
|
||||
return this.delegate.remove(pInput, pKey);
|
||||
}
|
||||
|
||||
public boolean compressMaps() {
|
||||
return this.delegate.compressMaps();
|
||||
}
|
||||
|
||||
public ListBuilder<T> listBuilder() {
|
||||
return new ListBuilder.Builder<>(this);
|
||||
}
|
||||
|
||||
public RecordBuilder<T> mapBuilder() {
|
||||
return new RecordBuilder.MapBuilder<>(this);
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
|
||||
public class FileToIdConverter {
|
||||
private final String prefix;
|
||||
private final String extension;
|
||||
|
||||
public FileToIdConverter(String pPrefix, String pExtenstion) {
|
||||
this.prefix = pPrefix;
|
||||
this.extension = pExtenstion;
|
||||
}
|
||||
|
||||
public static FileToIdConverter json(String pName) {
|
||||
return new FileToIdConverter(pName, ".json");
|
||||
}
|
||||
|
||||
public ResourceLocation idToFile(ResourceLocation pId) {
|
||||
return pId.withPath(this.prefix + "/" + pId.getPath() + this.extension);
|
||||
}
|
||||
|
||||
public ResourceLocation fileToId(ResourceLocation pFile) {
|
||||
String s = pFile.getPath();
|
||||
return pFile.withPath(s.substring(this.prefix.length() + 1, s.length() - this.extension.length()));
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, Resource> listMatchingResources(ResourceManager pResourceManager) {
|
||||
return pResourceManager.listResources(this.prefix, (p_251986_) -> {
|
||||
return p_251986_.getPath().endsWith(this.extension);
|
||||
});
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, List<Resource>> listMatchingResourceStacks(ResourceManager pResourceManager) {
|
||||
return pResourceManager.listResourceStacks(this.prefix, (p_248700_) -> {
|
||||
return p_248700_.getPath().endsWith(this.extension);
|
||||
});
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.core.HolderOwner;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
|
||||
public class HolderSetCodec<E> implements Codec<HolderSet<E>> {
|
||||
private final ResourceKey<? extends Registry<E>> registryKey;
|
||||
private final Codec<Holder<E>> elementCodec;
|
||||
private final Codec<List<Holder<E>>> homogenousListCodec;
|
||||
private final Codec<Either<TagKey<E>, List<Holder<E>>>> registryAwareCodec;
|
||||
private final Codec<net.minecraftforge.registries.holdersets.ICustomHolderSet<E>> forgeDispatchCodec;
|
||||
private final Codec<Either<net.minecraftforge.registries.holdersets.ICustomHolderSet<E>, Either<TagKey<E>, List<Holder<E>>>>> combinedCodec;
|
||||
|
||||
private static <E> Codec<List<Holder<E>>> homogenousList(Codec<Holder<E>> pHolderCodec, boolean pDisallowInline) {
|
||||
Codec<List<Holder<E>>> codec = ExtraCodecs.validate(pHolderCodec.listOf(), ExtraCodecs.ensureHomogenous(Holder::kind));
|
||||
return pDisallowInline ? codec : Codec.either(codec, pHolderCodec).xmap((p_206664_) -> {
|
||||
return p_206664_.map((p_206694_) -> {
|
||||
return p_206694_;
|
||||
}, List::of);
|
||||
}, (p_206684_) -> {
|
||||
return p_206684_.size() == 1 ? Either.right(p_206684_.get(0)) : Either.left(p_206684_);
|
||||
});
|
||||
}
|
||||
|
||||
public static <E> Codec<HolderSet<E>> create(ResourceKey<? extends Registry<E>> pRegistryKey, Codec<Holder<E>> pHolderCodec, boolean pDisallowInline) {
|
||||
return new HolderSetCodec<>(pRegistryKey, pHolderCodec, pDisallowInline);
|
||||
}
|
||||
|
||||
private HolderSetCodec(ResourceKey<? extends Registry<E>> p_206660_, Codec<Holder<E>> p_206661_, boolean p_206662_) {
|
||||
this.registryKey = p_206660_;
|
||||
this.elementCodec = p_206661_;
|
||||
this.homogenousListCodec = homogenousList(p_206661_, p_206662_);
|
||||
this.registryAwareCodec = Codec.either(TagKey.hashedCodec(p_206660_), this.homogenousListCodec);
|
||||
// FORGE: make registry-specific dispatch codec and make forge-or-vanilla either codec
|
||||
this.forgeDispatchCodec = ExtraCodecs.lazyInitializedCodec(() -> net.minecraftforge.registries.ForgeRegistries.HOLDER_SET_TYPES.get().getCodec())
|
||||
.dispatch(net.minecraftforge.registries.holdersets.ICustomHolderSet::type, type -> type.makeCodec(p_206660_, p_206661_, p_206662_));
|
||||
this.combinedCodec = new ExtraCodecs.EitherCodec<>(this.forgeDispatchCodec, this.registryAwareCodec);
|
||||
}
|
||||
|
||||
public <T> DataResult<Pair<HolderSet<E>, T>> decode(DynamicOps<T> p_206696_, T p_206697_) {
|
||||
if (p_206696_ instanceof RegistryOps<T> registryops) {
|
||||
Optional<HolderGetter<E>> optional = registryops.getter(this.registryKey);
|
||||
if (optional.isPresent()) {
|
||||
HolderGetter<E> holdergetter = optional.get();
|
||||
// FORGE: use the wrapped codec to decode custom/tag/list instead of just tag/list
|
||||
return this.combinedCodec.decode(p_206696_, p_206697_).map((p_206682_) -> {
|
||||
return p_206682_.mapFirst((p_206679_) -> {
|
||||
return p_206679_.map(java.util.function.Function.identity(), tagOrList -> tagOrList.map(holdergetter::getOrThrow, HolderSet::direct));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this.decodeWithoutRegistry(p_206696_, p_206697_);
|
||||
}
|
||||
|
||||
public <T> DataResult<T> encode(HolderSet<E> p_206674_, DynamicOps<T> p_206675_, T p_206676_) {
|
||||
if (p_206675_ instanceof RegistryOps<T> registryops) {
|
||||
Optional<HolderOwner<E>> optional = registryops.owner(this.registryKey);
|
||||
if (optional.isPresent()) {
|
||||
if (!p_206674_.canSerializeIn(optional.get())) {
|
||||
return DataResult.error(() -> {
|
||||
return "HolderSet " + p_206674_ + " is not valid in current registry set";
|
||||
});
|
||||
}
|
||||
|
||||
// FORGE: use the dispatch codec to encode custom holdersets, otherwise fall back to vanilla tag/list
|
||||
if (p_206674_ instanceof net.minecraftforge.registries.holdersets.ICustomHolderSet<E> customHolderSet)
|
||||
return this.forgeDispatchCodec.encode(customHolderSet, p_206675_, p_206676_);
|
||||
return this.registryAwareCodec.encode(p_206674_.unwrap().mapRight(List::copyOf), p_206675_, p_206676_);
|
||||
}
|
||||
}
|
||||
|
||||
return this.encodeWithoutRegistry(p_206674_, p_206675_, p_206676_);
|
||||
}
|
||||
|
||||
private <T> DataResult<Pair<HolderSet<E>, T>> decodeWithoutRegistry(DynamicOps<T> p_206671_, T p_206672_) {
|
||||
return this.elementCodec.listOf().decode(p_206671_, p_206672_).flatMap((p_206666_) -> {
|
||||
List<Holder.Direct<E>> list = new ArrayList<>();
|
||||
|
||||
for(Holder<E> holder : p_206666_.getFirst()) {
|
||||
if (!(holder instanceof Holder.Direct)) {
|
||||
return DataResult.error(() -> {
|
||||
return "Can't decode element " + holder + " without registry";
|
||||
});
|
||||
}
|
||||
|
||||
Holder.Direct<E> direct = (Holder.Direct)holder;
|
||||
list.add(direct);
|
||||
}
|
||||
|
||||
return DataResult.success(new Pair<>(HolderSet.direct(list), p_206666_.getSecond()));
|
||||
});
|
||||
}
|
||||
|
||||
private <T> DataResult<T> encodeWithoutRegistry(HolderSet<E> p_206690_, DynamicOps<T> p_206691_, T p_206692_) {
|
||||
return this.homogenousListCodec.encode(p_206690_.stream().toList(), p_206691_, p_206692_);
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.Decoder;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.damagesource.DamageType;
|
||||
import net.minecraft.world.item.armortrim.TrimMaterial;
|
||||
import net.minecraft.world.item.armortrim.TrimPattern;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.MultiNoiseBiomeSourceParameterList;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction;
|
||||
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorPreset;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraft.world.level.levelgen.presets.WorldPreset;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
|
||||
import net.minecraft.world.level.levelgen.synth.NormalNoise;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class RegistryDataLoader {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final List<RegistryDataLoader.RegistryData<?>> WORLDGEN_REGISTRIES = List.of(new RegistryDataLoader.RegistryData<>(Registries.DIMENSION_TYPE, DimensionType.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.BIOME, Biome.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.CHAT_TYPE, ChatType.CODEC), new RegistryDataLoader.RegistryData<>(Registries.CONFIGURED_CARVER, ConfiguredWorldCarver.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.CONFIGURED_FEATURE, ConfiguredFeature.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.PLACED_FEATURE, PlacedFeature.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.STRUCTURE, Structure.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.STRUCTURE_SET, StructureSet.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.PROCESSOR_LIST, StructureProcessorType.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TEMPLATE_POOL, StructureTemplatePool.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.NOISE_SETTINGS, NoiseGeneratorSettings.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.NOISE, NormalNoise.NoiseParameters.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.DENSITY_FUNCTION, DensityFunction.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.WORLD_PRESET, WorldPreset.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.FLAT_LEVEL_GENERATOR_PRESET, FlatLevelGeneratorPreset.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TRIM_PATTERN, TrimPattern.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TRIM_MATERIAL, TrimMaterial.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.DAMAGE_TYPE, DamageType.CODEC), new RegistryDataLoader.RegistryData<>(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, MultiNoiseBiomeSourceParameterList.DIRECT_CODEC));
|
||||
public static final List<RegistryDataLoader.RegistryData<?>> DIMENSION_REGISTRIES = List.of(new RegistryDataLoader.RegistryData<>(Registries.LEVEL_STEM, LevelStem.CODEC));
|
||||
|
||||
public static RegistryAccess.Frozen load(ResourceManager pResourceManager, RegistryAccess pRegistryAccess, List<RegistryDataLoader.RegistryData<?>> pRegistryData) {
|
||||
Map<ResourceKey<?>, Exception> map = new HashMap<>();
|
||||
List<Pair<WritableRegistry<?>, RegistryDataLoader.Loader>> list = pRegistryData.stream().map((p_250249_) -> {
|
||||
return p_250249_.create(Lifecycle.stable(), map);
|
||||
}).toList();
|
||||
RegistryOps.RegistryInfoLookup registryops$registryinfolookup = createContext(pRegistryAccess, list);
|
||||
list.forEach((p_255508_) -> {
|
||||
p_255508_.getSecond().load(pResourceManager, registryops$registryinfolookup);
|
||||
});
|
||||
list.forEach((p_258223_) -> {
|
||||
Registry<?> registry = p_258223_.getFirst();
|
||||
|
||||
try {
|
||||
registry.freeze();
|
||||
} catch (Exception exception) {
|
||||
map.put(registry.key(), exception);
|
||||
}
|
||||
|
||||
});
|
||||
if (!map.isEmpty()) {
|
||||
logErrors(map);
|
||||
throw new IllegalStateException("Failed to load registries due to above errors");
|
||||
} else {
|
||||
return (new RegistryAccess.ImmutableRegistryAccess(list.stream().map(Pair::getFirst).toList())).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
private static RegistryOps.RegistryInfoLookup createContext(RegistryAccess pRegistryAccess, List<Pair<WritableRegistry<?>, RegistryDataLoader.Loader>> pRegistryLoaders) {
|
||||
final Map<ResourceKey<? extends Registry<?>>, RegistryOps.RegistryInfo<?>> map = new HashMap<>();
|
||||
pRegistryAccess.registries().forEach((p_255505_) -> {
|
||||
map.put(p_255505_.key(), createInfoForContextRegistry(p_255505_.value()));
|
||||
});
|
||||
pRegistryLoaders.forEach((p_258221_) -> {
|
||||
map.put(p_258221_.getFirst().key(), createInfoForNewRegistry(p_258221_.getFirst()));
|
||||
});
|
||||
return new RegistryOps.RegistryInfoLookup() {
|
||||
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> p_256014_) {
|
||||
return Optional.ofNullable((RegistryOps.RegistryInfo<T>) map.get(p_256014_));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static <T> RegistryOps.RegistryInfo<T> createInfoForNewRegistry(WritableRegistry<T> pRegistry) {
|
||||
return new RegistryOps.RegistryInfo<>(pRegistry.asLookup(), pRegistry.createRegistrationLookup(), pRegistry.registryLifecycle());
|
||||
}
|
||||
|
||||
private static <T> RegistryOps.RegistryInfo<T> createInfoForContextRegistry(Registry<T> pRegistry) {
|
||||
return new RegistryOps.RegistryInfo<>(pRegistry.asLookup(), pRegistry.asTagAddingLookup(), pRegistry.registryLifecycle());
|
||||
}
|
||||
|
||||
private static void logErrors(Map<ResourceKey<?>, Exception> pErrors) {
|
||||
StringWriter stringwriter = new StringWriter();
|
||||
PrintWriter printwriter = new PrintWriter(stringwriter);
|
||||
Map<ResourceLocation, Map<ResourceLocation, Exception>> map = pErrors.entrySet().stream().collect(Collectors.groupingBy((p_249353_) -> {
|
||||
return p_249353_.getKey().registry();
|
||||
}, Collectors.toMap((p_251444_) -> {
|
||||
return p_251444_.getKey().location();
|
||||
}, Map.Entry::getValue)));
|
||||
map.entrySet().stream().sorted(Entry.comparingByKey()).forEach((p_249838_) -> {
|
||||
printwriter.printf("> Errors in registry %s:%n", p_249838_.getKey());
|
||||
p_249838_.getValue().entrySet().stream().sorted(Entry.comparingByKey()).forEach((p_250688_) -> {
|
||||
printwriter.printf(">> Errors in element %s:%n", p_250688_.getKey());
|
||||
p_250688_.getValue().printStackTrace(printwriter);
|
||||
});
|
||||
});
|
||||
printwriter.flush();
|
||||
LOGGER.error("Registry loading errors:\n{}", (Object)stringwriter);
|
||||
}
|
||||
|
||||
private static String registryDirPath(ResourceLocation p_252033_) {
|
||||
return net.minecraftforge.common.ForgeHooks.prefixNamespace(p_252033_); // FORGE: add non-vanilla registry namespace to loader directory, same format as tag directory (see net.minecraft.tags.TagManager#getTagDir(ResourceKey))
|
||||
}
|
||||
|
||||
static <E> void loadRegistryContents(RegistryOps.RegistryInfoLookup p_256369_, ResourceManager p_256349_, ResourceKey<? extends Registry<E>> p_255792_, WritableRegistry<E> p_256211_, Decoder<E> p_256232_, Map<ResourceKey<?>, Exception> p_255884_) {
|
||||
String s = registryDirPath(p_255792_.location());
|
||||
FileToIdConverter filetoidconverter = FileToIdConverter.json(s);
|
||||
RegistryOps<JsonElement> registryops = RegistryOps.create(JsonOps.INSTANCE, p_256369_);
|
||||
|
||||
for(Map.Entry<ResourceLocation, Resource> entry : filetoidconverter.listMatchingResources(p_256349_).entrySet()) {
|
||||
ResourceLocation resourcelocation = entry.getKey();
|
||||
ResourceKey<E> resourcekey = ResourceKey.create(p_255792_, filetoidconverter.fileToId(resourcelocation));
|
||||
Resource resource = entry.getValue();
|
||||
|
||||
try (Reader reader = resource.openAsReader()) {
|
||||
JsonElement jsonelement = JsonParser.parseReader(reader);
|
||||
if (!net.minecraftforge.common.crafting.conditions.ICondition.shouldRegisterEntry(jsonelement)) continue;
|
||||
DataResult<E> dataresult = p_256232_.parse(registryops, jsonelement);
|
||||
E e = dataresult.getOrThrow(false, (p_248715_) -> {
|
||||
});
|
||||
p_256211_.register(resourcekey, e, resource.isBuiltin() ? Lifecycle.stable() : dataresult.lifecycle());
|
||||
} catch (Exception exception) {
|
||||
p_255884_.put(resourcekey, new IllegalStateException(String.format(Locale.ROOT, "Failed to parse %s from pack %s", resourcelocation, resource.sourcePackId()), exception));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface Loader {
|
||||
void load(ResourceManager pResourceManager, RegistryOps.RegistryInfoLookup pRegistryInfoLookup);
|
||||
}
|
||||
|
||||
public static record RegistryData<T>(ResourceKey<? extends Registry<T>> key, Codec<T> elementCodec) {
|
||||
Pair<WritableRegistry<?>, RegistryDataLoader.Loader> create(Lifecycle pRegistryLifecycle, Map<ResourceKey<?>, Exception> p_251565_) {
|
||||
WritableRegistry<T> writableregistry = new MappedRegistry<>(this.key, pRegistryLifecycle);
|
||||
RegistryDataLoader.Loader registrydataloader$loader = (p_255511_, p_255512_) -> {
|
||||
RegistryDataLoader.loadRegistryContents(p_255512_, p_255511_, this.key, writableregistry, this.elementCodec, p_251565_);
|
||||
};
|
||||
return Pair.of(writableregistry, registrydataloader$loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.core.HolderOwner;
|
||||
import net.minecraft.core.Registry;
|
||||
|
||||
/**
|
||||
* A codec that wraps a single element, or "file", within a registry. Possibly allows inline definitions, and always
|
||||
* falls back to the element codec (and thus writing the registry element inline) if it fails to decode from the
|
||||
* registry.
|
||||
*/
|
||||
public final class RegistryFileCodec<E> implements Codec<Holder<E>> {
|
||||
private final ResourceKey<? extends Registry<E>> registryKey;
|
||||
private final Codec<E> elementCodec;
|
||||
private final boolean allowInline;
|
||||
|
||||
/**
|
||||
* Creates a codec for a single registry element, which is held as an un-resolved {@code Supplier<E>}. Both inline
|
||||
* definitions of the object, and references to an existing registry element id are allowed.
|
||||
* @param pRegistryKey The registry which elements may belong to.
|
||||
* @param pElementCodec The codec used to decode either inline definitions, or elements before entering them into the
|
||||
* registry.
|
||||
*/
|
||||
public static <E> RegistryFileCodec<E> create(ResourceKey<? extends Registry<E>> pRegistryKey, Codec<E> pElementCodec) {
|
||||
return create(pRegistryKey, pElementCodec, true);
|
||||
}
|
||||
|
||||
public static <E> RegistryFileCodec<E> create(ResourceKey<? extends Registry<E>> pRegistryKey, Codec<E> pElementCodec, boolean pAllowInline) {
|
||||
return new RegistryFileCodec<>(pRegistryKey, pElementCodec, pAllowInline);
|
||||
}
|
||||
|
||||
private RegistryFileCodec(ResourceKey<? extends Registry<E>> pRegistryKey, Codec<E> pElementCodec, boolean pAllowInline) {
|
||||
this.registryKey = pRegistryKey;
|
||||
this.elementCodec = pElementCodec;
|
||||
this.allowInline = pAllowInline;
|
||||
}
|
||||
|
||||
public <T> DataResult<T> encode(Holder<E> pInput, DynamicOps<T> pOps, T pPrefix) {
|
||||
if (pOps instanceof RegistryOps<?> registryops) {
|
||||
Optional<HolderOwner<E>> optional = registryops.owner(this.registryKey);
|
||||
if (optional.isPresent()) {
|
||||
if (!pInput.canSerializeIn(optional.get())) {
|
||||
return DataResult.error(() -> {
|
||||
return "Element " + pInput + " is not valid in current registry set";
|
||||
});
|
||||
}
|
||||
|
||||
return pInput.unwrap().map((p_206714_) -> {
|
||||
return ResourceLocation.CODEC.encode(p_206714_.location(), pOps, pPrefix);
|
||||
}, (p_206710_) -> {
|
||||
return this.elementCodec.encode(p_206710_, pOps, pPrefix);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this.elementCodec.encode(pInput.value(), pOps, pPrefix);
|
||||
}
|
||||
|
||||
public <T> DataResult<Pair<Holder<E>, T>> decode(DynamicOps<T> pOps, T pInput) {
|
||||
if (pOps instanceof RegistryOps<?> registryops) {
|
||||
Optional<HolderGetter<E>> optional = registryops.getter(this.registryKey);
|
||||
if (optional.isEmpty()) {
|
||||
return DataResult.error(() -> {
|
||||
return "Registry does not exist: " + this.registryKey;
|
||||
});
|
||||
} else {
|
||||
HolderGetter<E> holdergetter = optional.get();
|
||||
DataResult<Pair<ResourceLocation, T>> dataresult = ResourceLocation.CODEC.decode(pOps, pInput);
|
||||
if (dataresult.result().isEmpty()) {
|
||||
return !this.allowInline ? DataResult.error(() -> {
|
||||
return "Inline definitions not allowed here";
|
||||
}) : this.elementCodec.decode(pOps, pInput).map((p_206720_) -> {
|
||||
return p_206720_.mapFirst(Holder::direct);
|
||||
});
|
||||
} else {
|
||||
Pair<ResourceLocation, T> pair = dataresult.result().get();
|
||||
ResourceKey<E> resourcekey = ResourceKey.create(this.registryKey, pair.getFirst());
|
||||
return holdergetter.get(resourcekey).map(DataResult::success).orElseGet(() -> {
|
||||
return DataResult.error(() -> {
|
||||
return "Failed to get element " + resourcekey;
|
||||
});
|
||||
}).map((p_255658_) -> {
|
||||
return Pair.of((Holder<E>)p_255658_, pair.getSecond());
|
||||
}).setLifecycle(Lifecycle.stable());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return this.elementCodec.decode(pOps, pInput).map((p_214212_) -> {
|
||||
return p_214212_.mapFirst(Holder::direct);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "RegistryFileCodec[" + this.registryKey + " " + this.elementCodec + "]";
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.core.HolderOwner;
|
||||
import net.minecraft.core.Registry;
|
||||
|
||||
public final class RegistryFixedCodec<E> implements Codec<Holder<E>> {
|
||||
private final ResourceKey<? extends Registry<E>> registryKey;
|
||||
|
||||
public static <E> RegistryFixedCodec<E> create(ResourceKey<? extends Registry<E>> p_206741_) {
|
||||
return new RegistryFixedCodec<>(p_206741_);
|
||||
}
|
||||
|
||||
private RegistryFixedCodec(ResourceKey<? extends Registry<E>> p_206723_) {
|
||||
this.registryKey = p_206723_;
|
||||
}
|
||||
|
||||
public <T> DataResult<T> encode(Holder<E> p_206729_, DynamicOps<T> p_206730_, T p_206731_) {
|
||||
if (p_206730_ instanceof RegistryOps<?> registryops) {
|
||||
Optional<HolderOwner<E>> optional = registryops.owner(this.registryKey);
|
||||
if (optional.isPresent()) {
|
||||
if (!p_206729_.canSerializeIn(optional.get())) {
|
||||
return DataResult.error(() -> {
|
||||
return "Element " + p_206729_ + " is not valid in current registry set";
|
||||
});
|
||||
}
|
||||
|
||||
return p_206729_.unwrap().map((p_206727_) -> {
|
||||
return ResourceLocation.CODEC.encode(p_206727_.location(), p_206730_, p_206731_);
|
||||
}, (p_274804_) -> {
|
||||
return DataResult.error(() -> {
|
||||
return "Elements from registry " + this.registryKey + " can't be serialized to a value";
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return DataResult.error(() -> {
|
||||
return "Can't access registry " + this.registryKey;
|
||||
});
|
||||
}
|
||||
|
||||
public <T> DataResult<Pair<Holder<E>, T>> decode(DynamicOps<T> p_206743_, T p_206744_) {
|
||||
if (p_206743_ instanceof RegistryOps<?> registryops) {
|
||||
Optional<HolderGetter<E>> optional = registryops.getter(this.registryKey);
|
||||
if (optional.isPresent()) {
|
||||
return ResourceLocation.CODEC.decode(p_206743_, p_206744_).flatMap((p_255515_) -> {
|
||||
ResourceLocation resourcelocation = p_255515_.getFirst();
|
||||
return optional.get().get(ResourceKey.create(this.registryKey, resourcelocation)).map(DataResult::success).orElseGet(() -> {
|
||||
return DataResult.error(() -> {
|
||||
return "Failed to get element " + resourcelocation;
|
||||
});
|
||||
}).map((p_256041_) -> {
|
||||
return Pair.of((Holder<E>)p_256041_, (T)p_255515_.getSecond());
|
||||
}).setLifecycle(Lifecycle.stable());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return DataResult.error(() -> {
|
||||
return "Can't access registry " + this.registryKey;
|
||||
});
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "RegistryFixedCodec[" + this.registryKey + "]";
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.HolderOwner;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
|
||||
public class RegistryOps<T> extends DelegatingOps<T> {
|
||||
private final RegistryOps.RegistryInfoLookup lookupProvider;
|
||||
|
||||
private static RegistryOps.RegistryInfoLookup memoizeLookup(final RegistryOps.RegistryInfoLookup pLookupProvider) {
|
||||
return new RegistryOps.RegistryInfoLookup() {
|
||||
private final Map<ResourceKey<? extends Registry<?>>, Optional<? extends RegistryOps.RegistryInfo<?>>> lookups = new HashMap<>();
|
||||
|
||||
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> p_256043_) {
|
||||
return (Optional<RegistryOps.RegistryInfo<T>>) this.lookups.computeIfAbsent(p_256043_, pLookupProvider::lookup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> RegistryOps<T> create(DynamicOps<T> pDelegate, final HolderLookup.Provider pRegistries) {
|
||||
return create(pDelegate, memoizeLookup(new RegistryOps.RegistryInfoLookup() {
|
||||
public <E> Optional<RegistryOps.RegistryInfo<E>> lookup(ResourceKey<? extends Registry<? extends E>> p_256323_) {
|
||||
return pRegistries.lookup(p_256323_).map((p_258224_) -> {
|
||||
return new RegistryOps.RegistryInfo<>(p_258224_, p_258224_, p_258224_.registryLifecycle());
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static <T> RegistryOps<T> create(DynamicOps<T> pDelegate, RegistryOps.RegistryInfoLookup pLookupProvider) {
|
||||
return new RegistryOps<>(pDelegate, pLookupProvider);
|
||||
}
|
||||
|
||||
private RegistryOps(DynamicOps<T> pDelegate, RegistryOps.RegistryInfoLookup pLookupProvider) {
|
||||
super(pDelegate);
|
||||
this.lookupProvider = pLookupProvider;
|
||||
}
|
||||
|
||||
public <E> Optional<HolderOwner<E>> owner(ResourceKey<? extends Registry<? extends E>> pRegistryKey) {
|
||||
return this.lookupProvider.lookup(pRegistryKey).map(RegistryOps.RegistryInfo::owner);
|
||||
}
|
||||
|
||||
public <E> Optional<HolderGetter<E>> getter(ResourceKey<? extends Registry<? extends E>> pRegistryKey) {
|
||||
return this.lookupProvider.lookup(pRegistryKey).map(RegistryOps.RegistryInfo::getter);
|
||||
}
|
||||
|
||||
public static <E, O> RecordCodecBuilder<O, HolderGetter<E>> retrieveGetter(ResourceKey<? extends Registry<? extends E>> p_206833_) {
|
||||
return ExtraCodecs.retrieveContext((p_274811_) -> {
|
||||
if (p_274811_ instanceof RegistryOps<?> registryops) {
|
||||
return registryops.lookupProvider.lookup(p_206833_).map((p_255527_) -> {
|
||||
return DataResult.success(p_255527_.getter(), p_255527_.elementsLifecycle());
|
||||
}).orElseGet(() -> {
|
||||
return DataResult.error(() -> {
|
||||
return "Unknown registry: " + p_206833_;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return DataResult.error(() -> {
|
||||
return "Not a registry ops";
|
||||
});
|
||||
}
|
||||
}).forGetter((p_255526_) -> {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static <E> com.mojang.serialization.MapCodec<HolderLookup.RegistryLookup<E>> retrieveRegistryLookup(ResourceKey<? extends Registry<? extends E>> resourceKey) {
|
||||
return ExtraCodecs.retrieveContext(ops -> {
|
||||
if (!(ops instanceof RegistryOps<?> registryOps))
|
||||
return DataResult.error(() -> "Not a registry ops");
|
||||
|
||||
return registryOps.lookupProvider.lookup(resourceKey).map(registryInfo -> {
|
||||
if (!(registryInfo.owner() instanceof HolderLookup.RegistryLookup<E> registryLookup))
|
||||
return DataResult.<HolderLookup.RegistryLookup<E>>error(() -> "Found holder getter but was not a registry lookup for " + resourceKey);
|
||||
|
||||
return DataResult.success(registryLookup, registryInfo.elementsLifecycle());
|
||||
}).orElseGet(() -> DataResult.error(() -> "Unknown registry: " + resourceKey));
|
||||
});
|
||||
}
|
||||
|
||||
public static <E, O> RecordCodecBuilder<O, Holder.Reference<E>> retrieveElement(ResourceKey<E> pKey) {
|
||||
ResourceKey<? extends Registry<E>> resourcekey = ResourceKey.createRegistryKey(pKey.registry());
|
||||
return ExtraCodecs.retrieveContext((p_274808_) -> {
|
||||
if (p_274808_ instanceof RegistryOps<?> registryops) {
|
||||
return registryops.lookupProvider.lookup(resourcekey).flatMap((p_255518_) -> {
|
||||
return p_255518_.getter().get(pKey);
|
||||
}).map(DataResult::success).orElseGet(() -> {
|
||||
return DataResult.error(() -> {
|
||||
return "Can't find value: " + pKey;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return DataResult.error(() -> {
|
||||
return "Not a registry ops";
|
||||
});
|
||||
}
|
||||
}).forGetter((p_255524_) -> {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static record RegistryInfo<T>(HolderOwner<T> owner, HolderGetter<T> getter, Lifecycle elementsLifecycle) {
|
||||
}
|
||||
|
||||
public interface RegistryInfoLookup {
|
||||
<T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> pRegistryKey);
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.mojang.serialization.Codec;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
|
||||
/**
|
||||
* An immutable key for a resource, in terms of the name of its parent registry and its location in that registry.
|
||||
* <p>
|
||||
* {@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".</p>
|
||||
* <p>
|
||||
* @param <T> 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<T> implements Comparable<ResourceKey<?>> {
|
||||
private static final ConcurrentMap<ResourceKey.InternKey, ResourceKey<?>> 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 <T> Codec<ResourceKey<T>> codec(ResourceKey<? extends Registry<T>> pRegistryKey) {
|
||||
return ResourceLocation.CODEC.xmap((p_195979_) -> {
|
||||
return create(pRegistryKey, p_195979_);
|
||||
}, 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 <T> ResourceKey<T> create(ResourceKey<? extends Registry<T>> pRegistryKey, ResourceLocation pLocation) {
|
||||
return create(pRegistryKey.location, pLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the created registry key. The registry name is set to {@code minecraft:root} and the location the
|
||||
* specified {@code registryName}.
|
||||
*/
|
||||
public static <T> ResourceKey<Registry<T>> createRegistryKey(ResourceLocation pLocation) {
|
||||
return create(BuiltInRegistries.ROOT_REGISTRY_NAME, pLocation);
|
||||
}
|
||||
|
||||
private static <T> ResourceKey<T> create(ResourceLocation pRegistryName, ResourceLocation pLocation) {
|
||||
return (ResourceKey<T>)VALUES.computeIfAbsent(new ResourceKey.InternKey(pRegistryName, pLocation), (p_258225_) -> {
|
||||
return new ResourceKey(p_258225_.registry, p_258225_.location);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceKey(ResourceLocation pRegistryName, ResourceLocation pLocation) {
|
||||
this.registryName = pRegistryName;
|
||||
this.location = pLocation;
|
||||
}
|
||||
|
||||
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<? extends Registry<?>> pRegistryKey) {
|
||||
return this.registryName.equals(pRegistryKey.location());
|
||||
}
|
||||
|
||||
public <E> Optional<ResourceKey<E>> cast(ResourceKey<? extends Registry<E>> pRegistryKey) {
|
||||
return this.isFor(pRegistryKey) ? Optional.of((ResourceKey<E>)this) : Optional.empty();
|
||||
}
|
||||
|
||||
public ResourceLocation location() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public ResourceLocation registry() {
|
||||
return this.registryName;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
return location.equals(((ResourceKey<?>) o).location) && registryName.equals(((ResourceKey<?>) o).registryName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceKey<?> o) {
|
||||
int ret = this.registry().compareTo(o.registry());
|
||||
if (ret == 0) ret = this.location().compareTo(o.location());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static record InternKey(ResourceLocation registry, ResourceLocation location) {
|
||||
}
|
||||
}
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
package net.minecraft.resources;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.function.UnaryOperator;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* An immutable location of a resource, in terms of a path and namespace.
|
||||
* <p>
|
||||
* This is used as an identifier for a resource, usually for those housed in a {@link net.minecraft.core.Registry}, such
|
||||
* as blocks and items.
|
||||
* <p>
|
||||
* {@code minecraft} is always taken as the default namespace for a resource location when none is explicitly stated.
|
||||
* When using this for registering objects, this namespace <strong>should</strong> only be used for resources added by
|
||||
* Minecraft itself.
|
||||
* <p>
|
||||
* Generally, and by the implementation of {@link #toString()}, the string representation of this class is expressed in
|
||||
* the form {@code namespace:path}. The colon is also used as the default separator for parsing strings as a {@code
|
||||
* ResourceLocation}.
|
||||
* @see net.minecraft.resources.ResourceKey
|
||||
*/
|
||||
public class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
public static final Codec<ResourceLocation> CODEC = Codec.STRING.comapFlatMap(ResourceLocation::read, ResourceLocation::toString).stable();
|
||||
private static final SimpleCommandExceptionType ERROR_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.id.invalid"));
|
||||
public static final char NAMESPACE_SEPARATOR = ':';
|
||||
public static final String DEFAULT_NAMESPACE = "minecraft";
|
||||
public static final String REALMS_NAMESPACE = "realms";
|
||||
private final String namespace;
|
||||
private final String path;
|
||||
|
||||
protected ResourceLocation(String pNamespace, String pPath, @Nullable ResourceLocation.Dummy pDummy) {
|
||||
this.namespace = pNamespace;
|
||||
this.path = pPath;
|
||||
}
|
||||
|
||||
public ResourceLocation(String pNamespace, String pPath) {
|
||||
this(assertValidNamespace(pNamespace, pPath), assertValidPath(pNamespace, pPath), (ResourceLocation.Dummy)null);
|
||||
}
|
||||
|
||||
private ResourceLocation(String[] pDecomposedLocation) {
|
||||
this(pDecomposedLocation[0], pDecomposedLocation[1]);
|
||||
}
|
||||
|
||||
public ResourceLocation(String pLocation) {
|
||||
this(decompose(pLocation, ':'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@code ResourceLocation} from the specified {@code location}, split into a namespace and path by the
|
||||
* specified {@code separator} char.
|
||||
* <p>
|
||||
* If the {@code separator} char is not present in the {@code location}, the namespace defaults to {@code minecraft},
|
||||
* taking the {@code location} as the path.
|
||||
* @throws net.minecraft.ResourceLocationException if there is a non {@code [a-z0-9_.-]} character in the decomposed
|
||||
* namespace or a non {@code [a-z0-9/._-]} character in the decomposed path.
|
||||
* @see #tryParse(String)
|
||||
* @see #isValidResourceLocation(String)
|
||||
* @param pLocation the location string to parse as a {@code ResourceLocation}
|
||||
* @param pSeparator the separator to separate the namespace and path by. This should not be any of these characters:
|
||||
* {@code [a-z0-9/._-]}.
|
||||
*/
|
||||
public static ResourceLocation of(String pLocation, char pSeparator) {
|
||||
return new ResourceLocation(decompose(pLocation, pSeparator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to parse the specified {@code location} as a {@code ResourceLocation} by splitting it into a
|
||||
* namespace and path by a colon.
|
||||
* <p>
|
||||
* If no colon is present in the {@code location}, the namespace defaults to {@code minecraft}, taking the {@code
|
||||
* location} as the path.
|
||||
* @return the parsed resource location; otherwise {@code null} if there is a non {@code [a-z0-9_.-]} character in
|
||||
* the decomposed namespace or a non {@code [a-z0-9/._-]} character in the decomposed path
|
||||
* @see #of(String, char)
|
||||
* @param pLocation the location string to try to parse as a {@code ResourceLocation}
|
||||
*/
|
||||
@Nullable
|
||||
public static ResourceLocation tryParse(String pLocation) {
|
||||
try {
|
||||
return new ResourceLocation(pLocation);
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ResourceLocation tryBuild(String pNamespace, String pPath) {
|
||||
try {
|
||||
return new ResourceLocation(pNamespace, pPath);
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static String[] decompose(String pLocation, char pSeparator) {
|
||||
String[] astring = new String[]{"minecraft", pLocation};
|
||||
int i = pLocation.indexOf(pSeparator);
|
||||
if (i >= 0) {
|
||||
astring[1] = pLocation.substring(i + 1);
|
||||
if (i >= 1) {
|
||||
astring[0] = pLocation.substring(0, i);
|
||||
}
|
||||
}
|
||||
|
||||
return astring;
|
||||
}
|
||||
|
||||
public static DataResult<ResourceLocation> read(String p_135838_) {
|
||||
try {
|
||||
return DataResult.success(new ResourceLocation(p_135838_));
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
return DataResult.error(() -> {
|
||||
return "Not a valid resource location: " + p_135838_ + " " + resourcelocationexception.getMessage();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return this.namespace;
|
||||
}
|
||||
|
||||
public ResourceLocation withPath(String pPath) {
|
||||
return new ResourceLocation(this.namespace, assertValidPath(this.namespace, pPath), (ResourceLocation.Dummy)null);
|
||||
}
|
||||
|
||||
public ResourceLocation withPath(UnaryOperator<String> pPathOperator) {
|
||||
return this.withPath(pPathOperator.apply(this.path));
|
||||
}
|
||||
|
||||
public ResourceLocation withPrefix(String pPathPrefix) {
|
||||
return this.withPath(pPathPrefix + this.path);
|
||||
}
|
||||
|
||||
public ResourceLocation withSuffix(String pPathSuffix) {
|
||||
return this.withPath(this.path + pPathSuffix);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.namespace + ":" + this.path;
|
||||
}
|
||||
|
||||
public boolean equals(Object pOther) {
|
||||
if (this == pOther) {
|
||||
return true;
|
||||
} else if (!(pOther instanceof ResourceLocation)) {
|
||||
return false;
|
||||
} else {
|
||||
ResourceLocation resourcelocation = (ResourceLocation)pOther;
|
||||
return this.namespace.equals(resourcelocation.namespace) && this.path.equals(resourcelocation.path);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 31 * this.namespace.hashCode() + this.path.hashCode();
|
||||
}
|
||||
|
||||
public int compareTo(ResourceLocation pOther) {
|
||||
int i = this.path.compareTo(pOther.path);
|
||||
if (i == 0) {
|
||||
i = this.namespace.compareTo(pOther.namespace);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Normal compare sorts by path first, this compares namespace first.
|
||||
public int compareNamespaced(ResourceLocation o) {
|
||||
int ret = this.namespace.compareTo(o.namespace);
|
||||
return ret != 0 ? ret : this.path.compareTo(o.path);
|
||||
}
|
||||
|
||||
public String toDebugFileName() {
|
||||
return this.toString().replace('/', '_').replace(':', '_');
|
||||
}
|
||||
|
||||
public String toLanguageKey() {
|
||||
return this.namespace + "." + this.path;
|
||||
}
|
||||
|
||||
public String toShortLanguageKey() {
|
||||
return this.namespace.equals("minecraft") ? this.path : this.toLanguageKey();
|
||||
}
|
||||
|
||||
public String toLanguageKey(String pType) {
|
||||
return pType + "." + this.toLanguageKey();
|
||||
}
|
||||
|
||||
public String toLanguageKey(String pType, String p_270199_) {
|
||||
return pType + "." + this.toLanguageKey() + "." + p_270199_;
|
||||
}
|
||||
|
||||
public static ResourceLocation read(StringReader pReader) throws CommandSyntaxException {
|
||||
int i = pReader.getCursor();
|
||||
|
||||
while(pReader.canRead() && isAllowedInResourceLocation(pReader.peek())) {
|
||||
pReader.skip();
|
||||
}
|
||||
|
||||
String s = pReader.getString().substring(i, pReader.getCursor());
|
||||
|
||||
try {
|
||||
return new ResourceLocation(s);
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
pReader.setCursor(i);
|
||||
throw ERROR_INVALID.createWithContext(pReader);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAllowedInResourceLocation(char pCharacter) {
|
||||
return pCharacter >= '0' && pCharacter <= '9' || pCharacter >= 'a' && pCharacter <= 'z' || pCharacter == '_' || pCharacter == ':' || pCharacter == '/' || pCharacter == '.' || pCharacter == '-';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the specified {@code path} is valid: consists only of {@code [a-z0-9/._-]} characters
|
||||
*/
|
||||
public static boolean isValidPath(String pPath) {
|
||||
for(int i = 0; i < pPath.length(); ++i) {
|
||||
if (!validPathChar(pPath.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the specified {@code namespace} is valid: consists only of {@code [a-z0-9_.-]} characters
|
||||
*/
|
||||
public static boolean isValidNamespace(String pNamespace) {
|
||||
for(int i = 0; i < pNamespace.length(); ++i) {
|
||||
if (!validNamespaceChar(pNamespace.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String assertValidNamespace(String pNamespae, String pPath) {
|
||||
if (!isValidNamespace(pNamespae)) {
|
||||
throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + pNamespae + ":" + pPath);
|
||||
} else {
|
||||
return pNamespae;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean validPathChar(char pPathChar) {
|
||||
return pPathChar == '_' || pPathChar == '-' || pPathChar >= 'a' && pPathChar <= 'z' || pPathChar >= '0' && pPathChar <= '9' || pPathChar == '/' || pPathChar == '.';
|
||||
}
|
||||
|
||||
public static boolean validNamespaceChar(char pNamespaceChar) {
|
||||
return pNamespaceChar == '_' || pNamespaceChar == '-' || pNamespaceChar >= 'a' && pNamespaceChar <= 'z' || pNamespaceChar >= '0' && pNamespaceChar <= '9' || pNamespaceChar == '.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the specified {@code location} into a namespace and path by a colon, checking both are valid.
|
||||
* <p>
|
||||
* If no colon is present in the {@code location}, the namespace defaults to {@code minecraft}, taking the {@code
|
||||
* location} as the path.</p>
|
||||
* @return {@code true} if both the decomposed namespace and path are valid
|
||||
* @see #isValidPath(String)
|
||||
* @see #isValidNamespace(String)
|
||||
*/
|
||||
public static boolean isValidResourceLocation(String pLocation) {
|
||||
String[] astring = decompose(pLocation, ':');
|
||||
return isValidNamespace(StringUtils.isEmpty(astring[0]) ? "minecraft" : astring[0]) && isValidPath(astring[1]);
|
||||
}
|
||||
|
||||
private static String assertValidPath(String pNamespace, String pPath) {
|
||||
if (!isValidPath(pPath)) {
|
||||
throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + pNamespace + ":" + pPath);
|
||||
} else {
|
||||
return pPath;
|
||||
}
|
||||
}
|
||||
|
||||
protected interface Dummy {
|
||||
}
|
||||
|
||||
public static class Serializer implements JsonDeserializer<ResourceLocation>, JsonSerializer<ResourceLocation> {
|
||||
public ResourceLocation deserialize(JsonElement pJson, Type pTypeOfT, JsonDeserializationContext pContext) throws JsonParseException {
|
||||
return new ResourceLocation(GsonHelper.convertToString(pJson, "location"));
|
||||
}
|
||||
|
||||
public JsonElement serialize(ResourceLocation pResourceLocation, Type pTypeOfT, JsonSerializationContext pContext) {
|
||||
return new JsonPrimitive(pResourceLocation.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
@FieldsAreNonnullByDefault
|
||||
package net.minecraft.resources;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import net.minecraft.FieldsAreNonnullByDefault;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
Reference in new issue
Block a user