Modification de la génération du monde

  • Modification de la Génération de base

  • Créer une Base de Terrain Customisée

  • Créer des GenerationPopulators Customisés

  • Création de Populateurs Personnalisés

  • Création de Biomes Personnalisés

Modification de la Génération de base

Note

Cette page assume que vous êtes familier avec le paramétrage de votre WorldGeneratorModifier. Si ce n’est pas le cas, merci de lire l’article sur le paramétrage de votre modificateur à WorldGeneratorModifiers.

Sponge expose une grande partie de la génération de mondes de base, qui peut être manipulée à travers les différentes interfaces. Actuellement, les seuls éléments du processus de génération qui sont facilement exposés à la manipulation sont les populateurs.

Pour un petit exemple, regardons comment nous pourrions changer les cactus qui apparaissent dans les déserts pour les rendre plus grands.

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);
    }
}

Commeencez par récupérer le BiomeGenerationSettings pour le biome désert. Cet objet est un conteneur pour tous les paramètres de génération relatifs à ce biome. Ensuite, itérez à travers la liste de tous les populateurs Cactus et définissez la hauteur à 5, ce qui signifie qu’il peut seulement générer des cactus de 5 blocs de hauteur.

Note

Cactus#setHeight(int), et beaucoup d’autres méthodes similaires sur d’autres populateurs, prennent également un VariableAmount qui peut être utilisé pour spécifier la hauteur comme une plage ou une autre valeur personnalisée.

Ça a été un exemple simple sur comment modifier un populateur existant. Regardons comment nous pouvons ajouter une nouvelle instance d’un populateur de base. Cette fois le populateur va être ajouté globalement, ce qui signifie qu’il va être appliqués à tous les chunks, peu importe le biome. Ajoutons un populateur de citrouilles globalement, éparpillant des citrouilles un peu partout dans le monde entier.

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);
}

Contrairement à l’exemple précédent, cette fois vous créez un tout nouveau populateur. Pour faire ceci, vous devez tout d’abord récupérer un builder pour ce populateur. Puis définissez vos paramètres souhaités pour le populateur à l’intérieur de celui-ci - dans ce cas, nous voulons une douzaine de citrouilles à faire apparaître pour chaque morceau. Finalement, ajoutez votre nouveau populateur à la liste des populateurs qui sont appliqués globalement dans le monde.

Voilà, nous avons maintenant des citrouilles partout.

Note

Dans cet exemple, nous avons ajouté un populateur de citrouille à la fin de la liste des populateurs, mais il est à noter que cette liste est dépendante de l’ordre. Donc si vous voulez que votre populateur soit appelé plus tôt que les autres populateurs, comme c’est habituellement une bonne idée avec les populateurs de forêts, alors vous devrez ajouter votre populateur au début de la liste.

Ces deux exemples devraient servir à vous aider à vous familiariser avec le domaine du travail avec les populateurs de base. Cela ne touche qu’à la surface de ce qui est possible. Voir les javadocs pour une liste complète des populateurs disponibles et leurs propriétés.

Créer une Base de Terrain Customisée

Modifier le GenerationPopulator de base d’un générateur de mondes vous permet de changer la génération de la forme de base du terrain dans le monde. Un populateur générateur suivra à peu près la procédure d’utilisation des informations de la seed et du biome pour seed et générer une série de cartes de bruit, depuis laquelle le terrain est formé. Le terrain créé dans un populateur générateur de base modifié devrait uniquement se composer de blocs de pierre, afin de permettre aux biomes de remplacer correctement les blocs pour la couverture du sol spécifique au biome.

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);
    }
}

Cet un exemple assez simple d’un populateur de génération de terrain de base (au moins, si vous ne regardez pas les maths pour calculer la hauteur). Pour chaque colonne dans la zone en tampon nous voulons calculer une valeur de hauteur, et ensuite remplir tout ce qui est en dessous de cette hauteur avec de la pierre et laisser tout ce qui est au dessus en air (ou en eau si on est toujours sous le niveau de la mer).

Créer des GenerationPopulators Customisés

Note

L’API pour les GenerationPopulators personnalisés n’est pas encore terminée. Cette section sera élargie à l’avenir.

Création de Populateurs Personnalisés

Les populateurs personnalisés peuvent être utilisés poru ajouter une grande variété de fonctionnalités personnalisées. Pour créer un populateur personnalisé vous avez seulement besoin de créer une classe qui implémente l’interface Populator et de l’ajouter à la liste des populateurs attachés à un biome, ou à un générateur de mondes si vous voulez l’appliquer globalement.

Un Extent sera passé à votre populateur personnalisé qui est une vue sur le monde qui couvre la zone sur laquelle vous devriez appliquer votre populateur. Il est recommandé de ne pas faire d’hypothèses quant à la taille attendue ou de la position de cet extent, car il peut être plus large ou plus petit pour des opérations comme la régénération d’un chunk.

Note

Pour permettre à votre populateur de chevaucher les limites du chunk, votre populateur est autorisé à s’étendre jusqu’à 8 blocs en dehors des limites de l’extent.

Création de Biomes Personnalisés

Alors qu’il n’est actuellement pas possible de créer entièrement de nouveaux biomes avec Sponge, vous pouvez remplacer le système qui les dispose dans le monde en implémentant l’interface BiomeGenerator et en définissant votre générateur de biomes personnalisé sur un WorldGenerator.

Voici un exemple d’un générateur de biomes qui crée une grande île centrée autour 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);
                }
            }
        }
    }
}