Modificando la Generación Mundial

  • Modificando la Generación Vainilla

  • Creando Terreno de Base Personalizada

  • Creando GenerationPopulators Personalizados

  • Creando Populadores Personalizados

  • Creando Biomas Personalizados

Modificando la Generación Vainilla

Nota

Esta página asume que está familiarizado con la configuración de su WorldGeneratorModifier. De lo contrario, lea el artículo sobre cómo configurar su modificador en WorldGeneratorModifiers.

Sponge expone una gran cantidad de generación de mundo vainilla, que puede ser manipulada a través de las diversas interfaces. Actualmente, los únicos elementos del proceso de generación fácilmente expuestos a la manipulación son los pobladores.

Para un ejemplo rápido, vamos a ver cómo cambiaríamos los cactus que aparecen en los desiertos para que sean más altos.

import org.spongepowered.api.world.biome.BiomeGenerationSettings;
import org.spongepowered.api.world.biome.BiomeTypes;
import org.spongepowered.api.world.gen.Populator;
import org.spongepowered.api.world.gen.populator.Cactus;

@Override
public void modifyWorldGenerator(WorldCreationSettings world, DataContainer settings, WorldGenerator worldGenerator) {
    BiomeGenerationSettings desertSettings = worldGenerator.getBiomeSettings(BiomeTypes.DESERT);
    for (Cactus populator : desertSettings.getPopulators(Cactus.class)) {
        populator.setHeight(5);
    }
}

Comience obteniendo el BiomeGenerationSettings para el bioma del desierto. Este objeto es un contenedor para todas las configuraciones de generación relacionadas con ese bioma. A continuación, recorra la lista de todos los Cactus populadores y establezca la altura en 5, lo que significa que solo puede generar cactus de 5 bloques de altura.

Nota

El Cactus#setHeight(int), y muchos otros métodos similares en otras poblaciones, también toma un VariableAmount que se puede usar para especificar la altura como un rango u otro valor personalizado.

Este ha sido un ejemplo simple de cómo modificar un populador existente. Vamos a ver cómo podemos agregar una nueva instancia de un populador vainilla. Esta vez, el populador se agregará globalmente, lo que significa que se aplicará a todos los fragmentos, independientemente del bioma. Agreguemos un populador de Calabaza globalmente, lo que provoca que las calabazas se dispersen por todo el mundo.

import org.spongepowered.api.world.gen.populator.Pumpkin;

@Override
public void modifyWorldGenerator(WorldCreationSettings world, DataContainer settings, WorldGenerator worldGenerator) {
    Pumpkin pumpkinPopulator = Pumpkin.builder().perChunk(12).build();
    worldGenerator.getPopulators().add(pumpkinPopulator);
}

Al contrario del ejemplo anterior, esta vez usted está creando un populador completamente nuevo. Para hacer esto, primero necesita obtener un constructor para ese populador. Luego configure las configuraciones deseadas para el populador dentro de este - en este caso, queremos una docena de calabazas para engendrar por parche. Finalmente, agregue su nuevo populador a la lista de populadores que se aplican globalmente al mundo.

Voila, ahora tenemos calabazas en todos lados.

Nota

En este ejemplo, agregamos el populator de calabaza al final de la lista de populadores, pero debe tenerse en cuenta que esta lista depende de la orden. Entonces, si desea que su populador se llame antes que otros populadores, como suele ser una buena idea con los populadores de Forest, entonces debería agregar su populator al comienzo de la lista.

Estos dos ejemplos deberían servir para ayudarlo a familiarizarse con el ámbito del trabajo con populadores vainilla. Esto solo toca la superficie de lo que es posible. Consulte los javadocs para obtener una lista completa de los populadores disponibles y sus propiedades.

Creando Terreno de Base Personalizada

Cambiar la base GenerationPopulator de un generador mundial le permite cambiar la forma de la generación del terreno base del mundo. Un populador generador seguirá aproximadamente el procedimiento de usar la información semilla y la información de la bioma para sembrar y modificar una serie de mapas, a partir de los cuales se forma el terreno. El terreno creado en un populador generador modificado debe consistir solo en bloques de piedra, para permitir que los biomas reemplacen adecuadamente los bloques para una cobertura del suelo específica del bioma.

public class SinusoidalGenerator implements GenerationPopulator {

    @Override
    public void populate(World world, MutableBlockVolume buffer, ImmutableBiomeArea biomes) {
        for(int x = buffer.getBlockMin().getX(); x < buffer.getBlockMax().getX(); x++) {
            for(int z = buffer.getBlockMin().getZ(); z < buffer.getBlockMax().getZ(); z++) {
                BiomeType biome = biomes.getBiome(x,z);
                int height = getHeight(x, z, world.getWorldGenerator().getBiomeSettings(biome));
                for(int y = 0; y < height || y < 64; y++) {
                    if(y < height) {
                        buffer.setBlockType(x, y, z, BlockTypes.STONE);
                    } else {
                        buffer.setBlockType(x, y, z, BlockTypes.WATER);
                    }
                }
            }
        }
    }

    private int getHeight(int x, int z, BiomeGenerationSettings biome) {
        double sx = Math.sin(x / 64d) + 1;
        double sz = Math.sin(z / 64d) + 1;
        double value = (sx + sz) / 4d;
        double heightRange = biome.getMaxHeight() - biome.getMinHeight();
        double height = heightRange * value / biome.getMinHeight();
        return GenericMath.floor(height * 256);
    }
}

Este es un ejemplo bastante simple de un populador de generación de terreno base (al menos, si mira más allá de las matemáticas para calcular la altura). Para cada columna en el área amortiguada queremos calcular un valor de altura, y luego rellenar todo lo que está debajo con piedra y dejar todo sobre él como aire (o agua si aún estamos debajo del nivel del mar).

Creando GenerationPopulators Personalizados

Nota

La API para GenerationPopulators personalizados aún no está terminada. Esta sección se ampliará en el futuro.

Creando Populadores Personalizados

Los populadores personalizados pueden ser usados para agregar una gran variedad de características personalizadas. Para crear un populator personalizado, usted solo necesita crear una clase que implemente la interfaz de Populator y agregarla a la lista de populadores adjuntos a un bioma, o a un generador mundial si desea que se aplique globalmente.

Su populator personalizado recibirá un Extent que es una vista del mundo que cubre el área donde debería aplicar su populador. Se recomienda que no haga ninguna suposición sobre el tamaño o la posición esperada de este alcance, ya que puede ser mayor o menor para operaciones tales como la regeneración de un fragmento.

Nota

Para permitir que su populator se superponga con los límites de los fragmentos, su populador puede extenderse hasta 8 bloques por fuera de los límites del alcance.

Creando Biomas Personalizados

Si bien actualmente no es posible crear biomas completamente nuevos dentro de Sponge, puede reemplazar el sistema por el que están organizados en el mundo implementando la interfaz BiomeGenerator y configurando su generador de bioma personalizado en un WorldGenerator.

A continuación se muestra un ejemplo de un generador de bioma que crea una gran isla centrada alrededor de (0, 0).

public class IslandBiomeGen implements BiomeGenerator {

    private static final double ISLAND_SIZE = 200f;
    private static final double BEACH_RADIUS = ISLAND_SIZE * ISLAND_SIZE;
    private static final double FOREST_SIZE = ISLAND_SIZE - 7;
    private static final double FOREST_RADIUS = FOREST_SIZE * FOREST_SIZE;
    private static final double HILLS_SIZE = FOREST_SIZE - 120;
    private static final double HILLS_RADIUS = HILLS_SIZE * HILLS_SIZE;

    @Override
    public void generateBiomes(MutableBiomeArea buffer) {
        Vector2i min = buffer.getBiomeMin();
        Vector2i max = buffer.getBiomeMax();

        for (int x = min.getX(); x <= max.getX(); x++) {
            for (int y = min.getY(); y <= max.getY(); y++) {
                if (x * x + y * y < HILLS_RADIUS) {
                    buffer.setBiome(x, y, BiomeTypes.EXTREME_HILLS);
                } else if (x * x + y * y < FOREST_RADIUS) {
                    buffer.setBiome(x, y, BiomeTypes.FOREST);
                } else if (x * x + y * y < BEACH_RADIUS) {
                    buffer.setBiome(x, y, BiomeTypes.BEACH);
                } else {
                    buffer.setBiome(x, y, BiomeTypes.OCEAN);
                }
            }
        }
    }
}