Zones - ToCraft/CraftedTerrainGeneration GitHub Wiki

Registering Zones via Data Packs

Zones are intended to tell CTGen, what specifications and biomes are mapped to what color on the map image. Here's the general file structure for a Zone:

{
  "biome": "minecraft:deep_ocean",
  "color": "#002355",
  "terrain_modifier": 6.0,
  "pixel_weight": 1
}

Here's a detailed explanation of each parameter:

Parameter Description
color required, color on the biome map in hex decimal layout (RGB)
biome required, the biome the color is mapped to
terrain_modifier optional (default: 4), in addition to the height on the heightmap, a noise value is added. This defines how strongly the noise can swing -> 6 means, hills are up to 6 blocks high, thales can be up to 6 blocks deep. Will be modified by transition
pixel_weight optional (default: 1), this is only used for preprocessing. A higher weight causes the zone to more aggressively spread

Prebuild

You can view all Zones that are shipped with CTGen in the source code. Those zones are used by Elarth. They are also listed here:

  • ctgen:lake - #0053d9 - lake at the sea level
  • ctgen:river - #0162ff - river at the sea level
  • ctgen:ocean - #002a67 - ocean at the sea level
  • ctgen:deep_ocean - #002355 - deep ocean at the sea level
  • ctgen:frozen_river - #5791f0 - frozen river at the sea level
  • ctgen:frozen_lake - #4e7ecc - frozen lake at the sea level
  • ctgen:stony_flats - #828c82 - flat stony area
  • ctgen:snowy_flats - #d9d9d9 - flat snowy area
  • ctgen:snowy_slopes - #c0c0c0 - similar to plains but with snow
  • ctgen:snowy_mountains - #a8a8a8 - big mountains that are snowed in
  • ctgen:plains - #395f39 - plains biome
  • ctgen:forest - #2b462b - forest biome
  • ctgen:hills - #979797 - transition between normal terrain (as taiga, plains, forest, ...) and ctgen:mountains
  • ctgen:mountains - #828282 - big stony mountains
  • ctgen:desert - #a5ab36 - desert biome
  • ctgen:badlands - #545438 - custom badlands biome
  • ctgen:badlands_mountains - #464735 - mountains with custom badlands biome

If you want to use any of these Zones in java, use the Zones class:

public final class Zones {
    // Northern Continent
    public static final ResourceKey<Zone> STONY_FLATS = getKey("stony_flats");
    public static final ResourceKey<Zone> SNOWY_FLATS = getKey("snowy_flats");
    public static final ResourceKey<Zone> SNOWY_SLOPES = getKey("snowy_slopes");
    public static final ResourceKey<Zone> SNOWY_MOUNTAINS = getKey("snowy_mountains");
    public static final ResourceKey<Zone> FROZEN_LAKE = getKey("frozen_lake");
    public static final ResourceKey<Zone> FROZEN_RIVER = getKey("frozen_river");
    // Eastern Continent
    public static final ResourceKey<Zone> PLAINS = getKey("plains");
    public static final ResourceKey<Zone> FOREST = getKey("forest");
    public static final ResourceKey<Zone> HILLS = getKey("hills");
    public static final ResourceKey<Zone> MOUNTAINS = getKey("mountains");
    public static final ResourceKey<Zone> LAKE = getKey("lake");
    // Western Continent
    public static final ResourceKey<Zone> DESERT = getKey("desert");
    public static final ResourceKey<Zone> BADLANDS = getKey("badlands");
    public static final ResourceKey<Zone> BADLANDS_MOUNTAINS = getKey("badlands_mountains");
    // General Water Biomes
    public static final ResourceKey<Zone> RIVER = getKey("river");
    public static final ResourceKey<Zone> OCEAN = getKey("ocean");
    public static final ResourceKey<Zone> DEEP_OCEAN = getKey("deep_ocean");
}

Registering Zones in Java

To create a custom zone in java, use code, similar to the following:

new ZoneBuilder().setBiome(getBiome(context, Biomes.STONY_SHORE)).setColor(new Color(130, 140, 130)).build();

Zones created in Java must be registered by bootstrapping them in to CTRegistries.ZONES_KEY during the runData task. No matter if running on Forge, Fabric or NeoForge, code similar to this one will be required:

public final class Zones {
    public static final ResourceKey<Zone> OCEAN = getKey("ocean");
    public static final ResourceKey<Zone> DEEP_OCEAN = getKey("deep_ocean");
    
    public static void bootstrap(@NotNull BootstapContext<Zone> context) {
        context.register(OCEAN, new ZoneBuilder().setBiome(getBiome(context, Biomes.OCEAN)).setColor(new Color(0, 42, 103)).setHeight(-35).setTerrainModifier(16).build());
        context.register(DEEP_OCEAN, new ZoneBuilder().setBiome(getBiome(context, Biomes.DEEP_OCEAN)).setColor(new Color(0, 35, 85)).setHeight(-60).setTerrainModifier(33).build());
    }

    private static @NotNull Holder<Biome> getBiome(@NotNull BootstapContext<?> context, ResourceKey<Biome> biome) {
        return context.lookup(Registries.BIOME).getOrThrow(biome);
    }

    private static @NotNull ResourceKey<Zone> getKey(String name) {
        return ResourceKey.create(CTRegistries.ZONES_KEY, new ResourceLocation(YourMod.MODID, name));
    }
}

For Fabric, this code snippet is used in CTGen:

public final class CTGDataGen implements DataGeneratorEntrypoint {
    private static final RegistrySetBuilder BUILDER = new RegistrySetBuilder().add(CTRegistries.ZONES_KEY, Zones::bootstrap);

    @Override
    public void onInitializeDataGenerator(@NotNull FabricDataGenerator generator) {
        FabricDataGenerator.Pack pack = generator.createPack();
        // generate zones
        pack.addProvider((FabricDataGenerator.Pack.RegistryDependentFactory<DataProvider>) (output, registriesFuture) ->
                new RegistriesDatapackGenerator(output, registriesFuture.thenComposeAsync(registries -> CompletableFuture.supplyAsync(() -> {
                    RegistryAccess.Frozen frozen = RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY);
                    return BUILDER.buildPatch(frozen, registries);
                }))));
    }
}

For Forge, it would look like the following code:

@Mod.EventBusSubscriber(modid = MyMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class DataGenerators {
    @SubscribeEvent
    public static void gatherData(GatherDataEvent event) {
        DataGenerator generator = event.getGenerator();
        PackOutput packOutput = generator.getPackOutput();
        CompletableFuture<HolderLookup.Provider> lookupProvider = event.getLookupProvider();

        generator.addProvider(event.includeServer(), new MyRegistryDataProvider(packOutput, lookupProvider));
    }
}

public class MyRegistryDataProvider extends DatapackBuiltinEntriesProvider {
    private static final RegistrySetBuilder BUILDER = new RegistrySetBuilder().add(CTRegistries.ZONES_KEY, Zones::bootstrap);

    public ModWorldGenProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
        super(output, registries, BUILDER, Set.of(AGoTMod.MOD_ID));
    }
}
⚠️ **GitHub.com Fallback** ⚠️