Skip to content

Instantly share code, notes, and snippets.

@SizableShrimp
Created February 27, 2023 04:35
Show Gist options
  • Save SizableShrimp/0593a53cc10adde557cece4399e2b912 to your computer and use it in GitHub Desktop.
Save SizableShrimp/0593a53cc10adde557cece4399e2b912 to your computer and use it in GitHub Desktop.
Datapack registry holder datagen 1.19.2
import com.google.gson.JsonElement;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DynamicOps;
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import java.nio.file.Path;
import java.util.Map;
public abstract class DatapackRegistryProvider<T> implements DataProvider {
private static final Logger LOGGER = LogUtils.getLogger();
protected final DataGenerator dataGenerator;
protected final ExistingFileHelper existingFileHelper;
protected final String modid;
protected final DynamicOps<JsonElement> registryOps;
protected final PackType packType;
protected final String directory;
protected final Codec<T> codec;
private final Map<ResourceLocation, T> entries;
@SuppressWarnings("unchecked")
public DatapackRegistryProvider(DataGenerator dataGenerator, ExistingFileHelper existingFileHelper, RegistryAccess registryAccess, DynamicOps<JsonElement> registryOps,
ResourceKey<? extends Registry<T>> registryKey, String modid) {
this.packType = PackType.SERVER_DATA;
this.dataGenerator = dataGenerator;
this.existingFileHelper = existingFileHelper;
this.modid = modid;
this.registryOps = registryOps;
final ResourceLocation registryId = registryKey.location();
// Minecraft datapack registry folders are in data/json-namespace/registry-name/
// Non-vanilla registry folders are data/json-namespace/registry-namespace/registry-name/
this.directory = registryId.getNamespace().equals("minecraft")
? registryId.getPath()
: registryId.getNamespace() + "/" + registryId.getPath();
this.codec = (Codec<T>) RegistryAccess.REGISTRIES.get(registryKey).codec();
this.entries = this.getEntries(registryAccess, HolderGetterProvider.create(registryAccess));
// Track generated data so other data providers can validate if needed.
final ExistingFileHelper.ResourceType resourceType = new ExistingFileHelper.ResourceType(this.packType, ".json", directory);
for (ResourceLocation id : entries.keySet()) {
existingFileHelper.trackGenerated(id, resourceType);
}
}
@Override
public void run(final CachedOutput cache) {
final Path outputFolder = this.dataGenerator.getOutputFolder();
final String dataFolder = this.packType.getDirectory();
this.entries.forEach(LamdbaExceptionUtils.rethrowBiConsumer((id, value) -> {
final Path path = outputFolder.resolve(String.join("/", dataFolder, id.getNamespace(), this.directory, id.getPath() + ".json"));
JsonElement encoded = this.codec.encodeStart(this.registryOps, value)
.getOrThrow(false, msg -> LOGGER.error("Failed to encode {}: {}", path, msg));
DataProvider.saveStable(cache, encoded, path);
}));
}
public abstract Map<ResourceLocation, T> getEntries(RegistryAccess registryAccess, HolderGetterProvider holderGetterProvider);
@NotNull
@Override
public String getName() {
return String.format("%s generator for %s", this.directory, this.modid);
}
@FunctionalInterface
public interface HolderGetterProvider {
private static HolderGetterProvider create(RegistryAccess registryAccess) {
return new HolderGetterProvider() {
@Override
public <T> HolderGetter<T> getHolderGetterOrThrow(ResourceKey<? extends Registry<T>> registryKey) {
Registry<T> registry = registryAccess.registryOrThrow(registryKey);
return new HolderGetter<>() {
@Override
public Holder<T> getOrCreateHolderOrThrow(ResourceKey<T> key) {
return registry.getOrCreateHolderOrThrow(key);
}
@Override
public Holder<T> getOrCreateHolderOrThrow(ResourceLocation key) {
return registry.getOrCreateHolderOrThrow(ResourceKey.create(registryKey, key));
}
};
}
};
}
<T> HolderGetter<T> getHolderGetterOrThrow(ResourceKey<? extends Registry<T>> registryKey);
}
public interface HolderGetter<T> {
Holder<T> getOrCreateHolderOrThrow(ResourceKey<T> key);
Holder<T> getOrCreateHolderOrThrow(ResourceLocation key);
}
}
public class Demo {
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
boolean includeServer = event.includeServer();
boolean includeClient = event.includeClient();
RegistryAccess registryAccess = RegistryAccess.builtinCopy();
RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, registryAccess);
// ...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment