Layers
Generate Minecraft worlds by map images!
Block Layers define what Block Placer should be used for which block position (e.g. -100, 0, 234). It’s recommended to have layers with the following names: deepslate
, stone
, dirt
, surface
, sea.
. Those layer names are also used in the implemented Zones. By default, CTGen ships for different layer types, explained below.
Height Layer
This layer type depends on the absolute y value of the block, e.g. -64 to 256.
{
"type": "ctgen:height_layer",
"min": -65,
"max": 0,
"limit_to_surface": true,
"shift": true,
"name": "deepslate",
"has_caves": true,
"fallback": "minecraft:deepslate"
}
min
- min y where the layer is appliedmax
- max y where the layer is appliedlimit_to_surface
- whether the layer should stop on the surface level, if the surface is below “max”shift
- whether the layer transition should be “shifted” for each block. adds a bit more beautiful noise to itname
- the name of the layer so Zones can modify ithas_caves
- whether carvers should be applied within this layerfallback
- a fallback block player in case the current zone doesn’t have a custom one
The exact same layer will look like this if coded in Java:
BlockLayer layer = new HeightLayer(-65, 0, true, true, "deepslate", true, new BasicPlacer(Blocks.DEEPSLATE));
Weight Layer
This layer type depends on the relative y - y in percent between minY and surface height. If the minimum y is -64 and the surface is at 70, then y = -64 will be 0, y = 70 will be 1.
{
"type": "ctgen:weight_layer",
"min_percentage": 0,
"max_percentage": 0.96,
"shift": true,
"name": "stone",
"has_caves": true,
"fallback": "minecraft:stone"
}
min_percentage
- min y in percent between the minimum y and the surfacemax_percentage
- max y in percent between the minimum y and the surfaceshift
- whether the layer transition should be “shifted” for each block. adds a bit more beautiful noise to itname
- the name of the layer so Zones can modify ithas_caves
- whether carvers should be applied within this layerfallback
- a fallback block player in case the current zone doesn’t have a custom one
The exact same layer will look like this if coded in Java:
BlockLayer layer = new WeightLayer(0D, 0.96D, true, "stone", true, new BasicPlacer(Blocks.STONE));
Sea Layer
This layer type fills every block between the surface and the sea level, if the surface is below the sea level.
{
"type": "ctgen:sea_layer",
"name": "sea",
"fallback": "minecraft:water"
}
name
- the name of the layer so Zones can modify itfallback
- a fallback block player in case the current zone doesn’t have a custom one
The exact same layer will look like this if coded in Java:
BlockLayer layer = new SeaLayer("sea", new BasicPlacer(Blocks.WATER));
Surface Layer
This layer type only applies on the surface block.
{
"type": "ctgen:surface_layer",
"name": "surface",
"fallback": "minecraft:grass_block"
}
name
- the name of the layer so Zones can modify itfallback
- a fallback block player in case the current zone doesn’t have a custom one
The exact same layer will look like this if coded in Java:
BlockLayer layer = new SurfaceLayer("surface", new BasicPlacer(Blocks.GRASS_BLOCK));
Registering Block Layer Types
You can also register a custom block layer using code similar to this one:
public class HeightLayer extends BlockLayer {
private final int min;
private final int max;
private final boolean limitedToSurface;
private final boolean hasShift;
public HeightLayer(int minY, int maxY, boolean limitedToSurface, boolean hasShift, String name, boolean hasCaves, BlockPlacer fallback) {
super(name, hasCaves, fallback);
this.min = minY;
this.max = maxY;
this.hasShift = hasShift;
this.limitedToSurface = limitedToSurface;
}
@Override
public boolean is(SimplexNoise noise, int x, int y, int z, Zone zone, int minY, int seaLevel, double surfaceHeight, int genHeight, int shift) {
int y2 = hasShift ? y + shift : y;
return y2 >= min - 1 && y2 <= max && (!limitedToSurface || y < surfaceHeight);
}
public static final Codec<HeightLayer> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("min").forGetter(o -> o.min),
Codec.INT.fieldOf("max").forGetter(o -> o.max),
Codec.BOOL.optionalFieldOf("limit_to_surface", true).forGetter(o -> o.limitedToSurface),
Codec.BOOL.optionalFieldOf("shift", true).forGetter(o -> o.hasShift),
Codec.STRING.fieldOf("name").forGetter(BlockLayer::getName),
Codec.BOOL.optionalFieldOf("has_caves", true).forGetter(BlockLayer::hasCaves),
BlockPlacer.CODEC.fieldOf("fallback").forGetter(BlockLayer::getFallback)
).apply(instance, instance.stable(HeightLayer::new)));
public static final ResourceLocation ID = new ResourceLocation(YourMod.MODID, "height_layer");
@Override
protected Codec<HeightLayer> codec() {
return CODEC;
}
}
To register the layer, just use this snippet:
CTRegistries.BLOCK_LAYER.register(HeightLayer.ID, HeightLayer.CODEC);
Continue with Placer