Created
April 17, 2022 18:59
-
-
Save Commoble/458506bbae386dac9432c77b3f8fe7f1 to your computer and use it in GitHub Desktop.
Datagenerating worldgen registry jsons in forge for minecraft 1.18.2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package biomecheeser; | |
import java.io.IOException; | |
import java.nio.file.Path; | |
import java.util.List; | |
import org.apache.logging.log4j.LogManager; | |
import org.apache.logging.log4j.Logger; | |
import com.google.gson.Gson; | |
import com.google.gson.GsonBuilder; | |
import com.google.gson.JsonElement; | |
import com.mojang.serialization.Codec; | |
import com.mojang.serialization.JsonOps; | |
import commoble.biomecheeser.BiomeCheeser; | |
import net.minecraft.core.Registry; | |
import net.minecraft.core.RegistryAccess; | |
import net.minecraft.data.DataGenerator; | |
import net.minecraft.data.DataProvider; | |
import net.minecraft.data.HashCache; | |
import net.minecraft.data.worldgen.placement.PlacementUtils; | |
import net.minecraft.resources.RegistryOps; | |
import net.minecraft.resources.ResourceKey; | |
import net.minecraft.resources.ResourceLocation; | |
import net.minecraft.server.packs.PackType; | |
import net.minecraft.world.level.block.Blocks; | |
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; | |
import net.minecraft.world.level.levelgen.feature.Feature; | |
import net.minecraft.world.level.levelgen.feature.configurations.BlockPileConfiguration; | |
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; | |
import net.minecraft.world.level.levelgen.placement.InSquarePlacement; | |
import net.minecraft.world.level.levelgen.placement.PlacedFeature; | |
import net.minecraftforge.eventbus.api.SubscribeEvent; | |
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; | |
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; | |
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; | |
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent; | |
import net.minecraftforge.registries.DeferredRegister; | |
import net.minecraftforge.registries.RegistryObject; | |
/* Example of generating data for jsons of worldgen registry objects */ | |
/* 1) use deferred registers and registry objects to register BuiltinRegistries objects such as configured/placed features | |
* 2) create the RegistryAccess and RegistryOps | |
* 3) get the relevant registry from the registryaccess | |
* 4) get the object from that registry | |
* 5) use the RegistryOps and direct codec to serialize it | |
*/ | |
@EventBusSubscriber(modid=BiomeCheeser.MODID, bus=Bus.MOD) | |
public class BiomeCheeserDatagen | |
{ | |
private static final Logger LOGGER = LogManager.getLogger(); | |
// 1) use deferred registers and registry objects to register BuiltinRegistries objects such as configured/placed features | |
// (even if you don't use them in java, this is needed for datagen) | |
public static <T> DeferredRegister<T> makeVanillaDeferredRegister(ResourceKey<Registry<T>> registryKey) | |
{ | |
DeferredRegister<T> register = DeferredRegister.create(registryKey, BiomeCheeser.MODID); | |
register.register(FMLJavaModLoadingContext.get().getModEventBus()); | |
return register; | |
} | |
private static final DeferredRegister<ConfiguredFeature<?,?>> CONFIGURED_FEATURES = makeVanillaDeferredRegister(Registry.CONFIGURED_FEATURE_REGISTRY); | |
private static final DeferredRegister<PlacedFeature> PLACED_FEATURES = makeVanillaDeferredRegister(Registry.PLACED_FEATURE_REGISTRY); | |
public static final String TNT_PILE_NAME = "tnt_pile"; | |
public static final ResourceKey<ConfiguredFeature<?,?>> CONFIGURED_TNT_PILE_KEY = ResourceKey.create(Registry.CONFIGURED_FEATURE_REGISTRY, new ResourceLocation(BiomeCheeser.MODID, TNT_PILE_NAME)); | |
private static final RegistryObject<ConfiguredFeature<?,?>> CONFIGURED_TNT_PILE = | |
CONFIGURED_FEATURES.register(TNT_PILE_NAME, | |
() -> new ConfiguredFeature<>(Feature.BLOCK_PILE, | |
new BlockPileConfiguration(BlockStateProvider.simple(Blocks.TNT)))); | |
public static final ResourceKey<PlacedFeature> PLACED_TNT_PILE_KEY = ResourceKey.create(Registry.PLACED_FEATURE_REGISTRY, new ResourceLocation(BiomeCheeser.MODID, TNT_PILE_NAME)); | |
private static final RegistryObject<PlacedFeature> PLACED_TNT_PILE = | |
PLACED_FEATURES.register(TNT_PILE_NAME, | |
() -> new PlacedFeature(CONFIGURED_TNT_PILE.getHolder().get(), | |
List.of(InSquarePlacement.spread(), PlacementUtils.HEIGHTMAP))); | |
@SubscribeEvent | |
public static void onGatherData(GatherDataEvent event) | |
{ | |
DataGenerator generator = event.getGenerator(); | |
Path outputFolder = generator.getOutputFolder(); | |
// 2) create the RegistryAccess and RegistryOps | |
RegistryAccess registries = RegistryAccess.builtinCopy(); | |
RegistryOps<JsonElement> ops = RegistryOps.create(JsonOps.INSTANCE, registries); | |
Gson gson = new GsonBuilder() | |
.setPrettyPrinting() | |
.create(); | |
// we use the helper method below to provide a list of resource keys of one registry type to make jsons for | |
generator.addProvider( | |
makeBuiltinRegistryProvider(BiomeCheeser.MODID, outputFolder, gson, ops, registries, Registry.CONFIGURED_FEATURE_REGISTRY, ConfiguredFeature.DIRECT_CODEC, | |
CONFIGURED_TNT_PILE_KEY)); | |
generator.addProvider( | |
makeBuiltinRegistryProvider(BiomeCheeser.MODID, outputFolder, gson, ops, registries, Registry.PLACED_FEATURE_REGISTRY, PlacedFeature.DIRECT_CODEC, | |
PLACED_TNT_PILE_KEY)); | |
} | |
/* Helper method that serializes many objects of the same registry type for us (note the vararg)*/ | |
@SafeVarargs | |
private static <T> DataProvider makeBuiltinRegistryProvider(String modid, Path outputFolder, Gson gson, RegistryOps<JsonElement> ops, RegistryAccess registries, ResourceKey<Registry<T>> registryKey, Codec<T> codec, ResourceKey<T>... keys) | |
{ | |
return new DataProvider() | |
{ | |
@Override | |
public void run(HashCache cache) throws IOException | |
{ | |
// 3) get the relevant registry from the registryaccess | |
// we must retrieve objects from registryaccess and not via our RegistryObject | |
// (as this is where RegistryOps looks up the id names of things to write out) | |
Registry<T> registry = registries.registryOrThrow(registryKey); | |
for (ResourceKey<T> key : keys) | |
{ | |
ResourceLocation id = key.location(); | |
Path path = outputFolder.resolve(String.join("/", PackType.SERVER_DATA.getDirectory(), id.getNamespace(), registryKey.location().getPath(), id.getPath()+".json")); | |
// 4) get the object from that registry | |
T t = registry.getOrThrow(key); | |
// 5) use the RegistryOps and direct codec to serialize it | |
// (as of 1.18.2 the indirect codec is no longer the correct codec for datagen) | |
codec.encodeStart(ops, t) | |
.resultOrPartial(msg -> LOGGER.error("Failed to encode {}: {}", path, msg)) | |
.ifPresent(json -> { | |
try | |
{ | |
DataProvider.save(gson, cache, json, path); | |
} | |
catch (IOException e) // we're inside this ifpresent so the throws can't deal with this | |
{ | |
e.printStackTrace(); | |
} | |
}); | |
} | |
} | |
@Override | |
public String getName() | |
{ | |
return modid + " " + registryKey.location().toString(); | |
} | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//data/biomecheeser/worldgen/configured_feature/tnt_pile.json | |
{ | |
"config": { | |
"state_provider": { | |
"state": { | |
"Properties": { | |
"unstable": "false" | |
}, | |
"Name": "minecraft:tnt" | |
}, | |
"type": "minecraft:simple_state_provider" | |
} | |
}, | |
"type": "minecraft:block_pile" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//data/biomecheeser/worldgen/placed_feature/tnt_pile.json | |
{ | |
"feature": "biomecheeser:tnt_pile", | |
"placement": [ | |
{ | |
"type": "minecraft:in_square" | |
}, | |
{ | |
"heightmap": "MOTION_BLOCKING", | |
"type": "minecraft:heightmap" | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment