Créer un nouveau World Type
-
Sommaire
Introduction
Dans le tutoriel suivant nous allons créer un world type (flat, default…) pour faire des mondes comme vous le voulez.
Pré-requis
- OpenClassrooms pour avoir des bonnes bases en java
- Un cerveau en bon état, que vous pouvez utiliser correctement
Code
Classe Principale:
Donc, nous commencerons en douceur avec une simple ligne dans la fonction “init” et “postInit”, il faut savoir que nous ne déclarerons pas nos biomes dans la classe principale, cependant vous pouvez le faire.
Ajoutez dans la fonction “init” :BiomeListTuto.BiomeList();
Et dans la fonction “postInit” :
BiomeListTuto.worldTypeTuto = new WorldTypeTuto();
La classe des biomes :
Cette classe est simple à condition que vous n’ajoutez pas d’autres biomes. Il vous faut seulement créer une fonction et ajouter une ligne :
public static WorldTypeTuto worldTypeTuto; public static void BiomeList() { }
Pour le moment vous devriez avoir une erreur.
World Type :
Maintenant nous allons créer notre classe WorldTypeTuto, ajouter l’extends WorldType.
Puis nous allons ajouter plusieurs fonctions :
public WorldTypeTuto() { } public GenLayer getBiomeLayer(long worldSeed,GenLayer parentLayer) { } public WorldChunkManager getChunkManager(World world) { }
- Dans la première nous ajoutons le nom et le WorldProvider
- Dans la seconde nous mettrons le BiomeGenLayer où nous mettrons tous les biomes que nous voulons avoir.
- Et dans la dernière nous déclarons le ChunkManager.
Ensuite, complétez la première fonction en ajoutant :
super("nomDeVotreType"); DimensionManager.unregisterProviderType(0); DimensionManager.registerProviderType(0, WorldProviderTuto.class, true);
Le “0” est l’ID de la dimension vous pouvez le changer. Ensuite, nous enregistrons la dimension.
Puis dans la seconde :
GenLayer ret = new BiomeGenLayerTuto(200L, parentLayer); ret = GenLayerZoom.magnify(1000L, ret, 2); ret = new GenLayerBiomeEdge(1000L, ret); return ret;
Nous enregistrons le BiomeGenLayer utilisé dans la génération du monde.
Et dans la troisième :return new WorldChunkManagerTuto(world);
ça retourne au WorldChunkManager
Vous devriez avoir des erreurs, il va falloir créer les autres classes.
La classe WorldProvider :
Donc je pense que nous allons faire la classe la plus simple :
Créez une classe et ajoutez l’extends :
extends WorldProviderSurface
Ensuite, vous pouvez ajouter :
public boolean canCoordinateBeSpawn(int par1, int par2) { return this.worldObj.getTopBlock(par1, par2) == Blocks.grass || this.worldObj.getTopBlock(par1, par2) == Blocks.sand || this.worldObj.getTopBlock(par1, par2) == Blocks.stone || this.worldObj.getTopBlock(par1, par2) == Blocks.snow_layer; }
Dans cette fonction, vous enregistrez tous les blocs où vous apparaissez. Normalement, vous pouvez ajouter encore des fonctions comme :
public String getDimensionName() { return "tuto"; }
Cela donne le nom de la dimension
public String getSaveFolder() { return "Tuto"; }
C’est le dossier ou sera enregistrée votre dimension
Vous pouvez ajouter toutes les fonctions d’une dimension.
La classe BiomeGenLayer :
Ajouter en extension la classe “GenLayer” et importez-la.
Ensuite, nous allons ajouter trois fonctions et un tableau.
protected BiomeGenBase[] baseBiomes = {/* votre biome */}; public BiomeGenLayerTuto(long seed, GenLayer genlayer) { } public BiomeGenLayerTuto(long seed) { } @Override public int[] getInts(int x, int z, int width, int depth) { }
Dans le tableau il faut mettre votre biome, si vous en avez d’autres tous devrons être “extends” le biome de base (il sera déclaré dans toutes les autres classes), vous pouvez aussi mettre des biomes de base et vous pouvez aussi mettre un autre tableau avec un autre nom.
exemple:protected BiomeGenBase[] baseBiomes = {BiomeGenBase.plains};
Donc dans la première fonction ajouter :
super(seed); this.parent = genlayer;
Donc le super permet d’utiliser le seed et le reste permet de générer par le constructeur
Dans la seconde fonction ajoutez :super(seed);
Comme plus haut ça nous permet d’utiliser le seed
et dans la dernière :int[] dest = IntCache.getIntCache(width * depth); for(int dz = 0; dz < depth; dz++) { }
Cela nous servira dans la génération de nos biomes
Complétez la boucle avec ceci :
for(int dx = 0; dx < width; dx++) { this.initChunkSeed(dx + x, dz + z); dest[(dx + dz * width)] = this.baseBiomes[nextInt(this.baseBiomes.length)].biomeID; }
La boucle permet d’augmenter la valeur du dx et le reste nous permet de générer nos biomes.
Après les deux boucles ajouter :
return dest;
La classe GenLayer :
Créer la classe en abstract et en extends “GenLayer”
ensuite ajouter deux fonctions :public GenLayerTuto(long seed) { super(seed); } public static GenLayer[] makeTheWorld(long seed) { }
ensuite compléter la seconde fonction :
GenLayer biomes = new BiomeGenLayerTuto(1L); biomes = new GenLayerZoom(1000L, biomes); biomes = new GenLayerZoom(1001L, biomes); biomes = new GenLayerZoom(1002L, biomes); biomes = new GenLayerZoom(1003L, biomes); biomes = new GenLayerZoom(1004L, biomes); biomes = new GenLayerZoom(1005L, biomes); GenLayer genlayervoronoizoom = new GenLayerVoronoiZoom(10L, biomes); biomes.initWorldGenSeed(seed); genlayervoronoizoom.initWorldGenSeed(seed); return new GenLayer[] {biomes, genlayervoronoizoom};
Ceci nous permet une génération dans notre monde.
La classe WorldChunkManager :
Nous nous attaquons à la classe la plus dure de tout le tutoriel et la plus longue.
Donc comme toujours créez une classe et ajoutez en extends “WorldChunkManager”.
Ensuite, ajoutez :
private GenLayer myGenBiomes; private GenLayer myBiomeIndexLayer; private BiomeCache myBiomeCache; private List <biomegenbase>myBiomesToSpawnIn;
Ensuite, ajouter :
public WorldChunkManagerTuto() { this.myBiomeCache = new BiomeCache(this); this.myBiomesToSpawnIn = new ArrayList<biomegenbase>(); this.myBiomesToSpawnIn.add(votreBiome); }
Dans cette fonction rien de savant.
Ensuite, ajouter :
public WorldChunkManagerTuto(World world) { this(world.getSeed(), world.provider.terrainType); } public List <biomegenbase>getBiomesToSpawnIn() { return this.myBiomesToSpawnIn; }
La première permet de définir le terrainType et la seconde le biome de spawn le plus probable (du moins le biome le plus présent, par défaut c’est l’océan).
public BiomeGenBase getBiomeGenAt(int x, int z) { BiomeGenBase biome = this.myBiomeCache.getBiomeGenAt(x, z); if(biome == null) { return /*VotreBiome*/; } return biome; }
Cela vous permet de générer vos biomes
public float[] getRainfall(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5) { if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5) { par1ArrayOfFloat = new float[par4 * par5]; } Arrays.fill(par1ArrayOfFloat, 0, par4 * par5, 0.0F); return par1ArrayOfFloat; } @SideOnly(Side.CLIENT) public float getTemperatureAtHeight(float par1, int par2) { return par1; }
La première fonction permet d’avoir de la pluie et neige et la deuxième ne vous en préoccuper pas, même si elle concerne les biome et la température.
public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5) { IntCache.resetIntCache(); if(par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5) { par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5]; } int[] aint = this.myGenBiomes.getInts(par2, par3, par4, par5); for(int i = 0; i < par4 * par5; ++i) { if(aint* >= 0) { par1ArrayOfBiomeGenBase* = BiomeGenBase.getBiome(aint*); } else { par1ArrayOfBiomeGenBase* = /*VotreBiome*/; } } return par1ArrayOfBiomeGenBase; }
Cela permet de générer votre biome (ou vos biomes)
public BiomeGenBase[] loadBlockGeneratorData(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5) { return this.getBiomeGenAt(par1ArrayOfBiomeGenBase, par2, par3, par4, par5, true); } public BiomeGenBase[] getBiomeGenAt(BiomeGenBase[] par1ArrayOfBiomeGenBase, int x, int y, int width, int length, boolean cacheFlag) { IntCache.resetIntCache(); if(par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < width * length) { par1ArrayOfBiomeGenBase = new BiomeGenBase[width * length]; } if(cacheFlag && width == 16 && length == 16 && (x & 15) == 0 && (y & 15) == 0) { BiomeGenBase[] abiomegenbase1 = this.myBiomeCache.getCachedBiomes(x, y); System.arraycopy(abiomegenbase1, 0, par1ArrayOfBiomeGenBase, 0, width * length); return par1ArrayOfBiomeGenBase; } else { int[] aint = this.myBiomeIndexLayer.getInts(x, y, width, length); for(int i = 0; i < width * length; ++i) { if(aint* >= 0) { par1ArrayOfBiomeGenBase* = BiomeGenBase.getBiome(aint*); } else { par1ArrayOfBiomeGenBase* = /*VotreBiome*/; } } return par1ArrayOfBiomeGenBase; } }
La première fonction permet de charger le générateur et les données.
La seconde fonction permet de charger la liste des biomes avec les bons blocs.Ajouter après :
public boolean areBiomesViable(int par1, int par2, int par3, List par4List) { IntCache.resetIntCache(); int l = par1 - par3 >> 2; int i1 = par2 - par3 >> 2; int j1 = par1 + par3 >> 2; int k1 = par2 + par3 >> 2; int l1 = j1 - l + 1; int i2 = k1 - i1 + 1; int[] aint = this.myGenBiomes.getInts(l, i1, l1, i2); for(int j2 = 0; j2 < l1 * i2; ++j2) { BiomeGenBase biomegenbase = BiomeGenBase.getBiome(aint[j2]); if(!par4List.contains(biomegenbase)) { return false; } } return true; }
Cela vérifie les biomes autoriser pour la génération.
public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, Random par5Random) { IntCache.resetIntCache(); int l = par1 - par3 >> 2; int i1 = par2 - par3 >> 2; int j1 = par1 + par3 >> 2; int k1 = par2 + par3 >> 2; int l1 = j1 - l + 1; int i2 = k1 - i1 + 1; int[] aint = this.myGenBiomes.getInts(l, i1, l1, i2); ChunkPosition chunkposition = null; int j2 = 0; for(int k2 = 0; k2 < l1 * i2; ++k2) { int l2 = l + k2 % l1 << 2; int i3 = i1 + k2 / l1 << 2; BiomeGenBase biomegenbase = BiomeGenBase.getBiome(aint[k2]); if(par4List.contains(biomegenbase) && (chunkposition == null || par5Random.nextInt(j2 + 1) == 0)) { chunkposition = new ChunkPosition(l2, 0, i3); ++j2; } } return chunkposition; } public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, Random par5Random) { IntCache.resetIntCache(); int l = par1 - par3 >> 2; int i1 = par2 - par3 >> 2; int j1 = par1 + par3 >> 2; int k1 = par2 + par3 >> 2; int l1 = j1 - l + 1; int i2 = k1 - i1 + 1; int[] aint = this.myGenBiomes.getInts(l, i1, l1, i2); ChunkPosition chunkposition = null; int j2 = 0; for(int k2 = 0; k2 < l1 * i2; ++k2) { int l2 = l + k2 % l1 << 2; int i3 = i1 + k2 / l1 << 2; BiomeGenBase biomegenbase = BiomeGenBase.getBiome(aint[k2]); if(par4List.contains(biomegenbase) && (chunkposition == null || par5Random.nextInt(j2 + 1) == 0)) { chunkposition = new ChunkPosition(l2, 0, i3); ++j2; } } return chunkposition; }
Cela va obtenir la position des biomes
public void cleanupCache() { this.myBiomeCache.cleanupCache(); }
Cela permet d’appeler le cleanupCache dans la classe BiomeCache, pour si jamais le monde n’est pas chargé dans les 30 secondes.
Nous avons fini avec cette classe, vous pouvez toujours ajouter d’autre fonctions.
Donc vous pouvez lancer votre monde et il devrait se génèrer, si jamais vous avez un problème regardez que le même biome a été mis partout,
Vous remarquerez que une petite chose qui vous gène, vous devrez seulement compléter votre .lang
Fichier .lang :
Allez dans votre fichier .lang et ajoutez cette ligne :
generator.tuto=Tuto World
Pour trouver le nom (le .tuto), allez dans votre classe WorldType et dans le super.
En démarrant normalement votre jeu vous devriez avoir tout de bien.Bonus
Dans ce bonus nous allons créer trois biomes et les générer dans notre nouveau monde (Ce n’est pas un tutoriel sur les biomes, donc je n’approfondirais pas le sujet).
La classe BiomeList:
Donc dans la classe biomes list créée au début du tutoriel déclarez vos biome :
public static BiomeGenBase tutoStonePlains, tutoMegaMountain;
Pour ce tutoriel j’ai décidé de créer une plaine de pierre et un biome de grandes montagnes.
Ensuite, nous allons déclarer deux hauteurs, une pour le biome plaine et une pour la montagne.
Donc ajoutez ceci:
protected static final BiomeGenBase.Height height_MidHills = new BiomeGenBase.Height(1.6F, 0.9F); protected static final BiomeGenBase.Height height_LowPlains = new BiomeGenBase.Height(0.125F, 0.03F);
Rien de scientifique, nous ajoutons :
- une height, de nom “height_MidHills” et “height_LowPlains”
- nous les initialisons, donc se sera des Height de la classe BiomeGenBase.
- Les deux float après sont :
- La hauteur pure
- Les variations
Donc comme vous le voyez dans les plaines nous avons mis une valeur très basse pour que ça reste relativement plat, et dans les montagnes nous avons fait le contraire.
Ensuite, dessous (dans la fonction en void) nous allons initialiser les biomes :
tutoStonePlains = new StonePlainsBiomes(50, true).setBiomeName("Stone Plains").setHeight(height_LowPlains).setTemperatureRainfall(0.8F, 0.4F); tutoMegaMountain = new MegaMountainBiomes(51, true).setBiomeName("Mega Mountain").setHeight(height_MidHills).setTemperatureRainfall(0.2F, 0.3F);
Donc nous initialisons:
- Nous ajoutons les classes de génération
- Après nous ajoutons l’ID du biomes
- Nous mettons sur true, pour les arbres
- Nous mettons le nom du biome (qui sont affichés en f5), il ne demande pas de fichier .lang.
- On définit la hauteur, dans notre cas les hauteurs juste au-dessus.
- On mat la température en premier float et en seconde nous mettons le taux de pluie.
La classe du biome plains :
Donc la classe de notre biome est relativement simple, donc à la classe que vous avez créé ajouter l’extends “BiomeGenBase”.
Puis ajoutez la ligne et la fonction :
private boolean field_150614_aC; public StonePlainsBiomes(int par1, boolean p_i45379_2_) { super(par1); this.topBlock = Blocks.stone; this.fillerBlock = Blocks.stone; this.field_150614_aC = p_i45379_2_; }
Donc:
- topBlock sera le bloc qui recouvrira notre biome
- fillerBlock sera le bloc just dessous, normalement la “terre”
Ensuite, ajoutez :
public void genTerrainBlocks(World p_150573_1_, Random p_150573_2_, Block[] p_150573_3_, byte[] p_150573_4_, int p_150573_5_, int p_150573_6_, double p_150573_7_) { this.generateBiomeTerrain(p_150573_1_, p_150573_2_, p_150573_3_, p_150573_4_, p_150573_5_, p_150573_6_, p_150573_7_); }
Cela nous permettra de lancer la prochaine fonction.
La fonction de génération est :public void generateBiomeTerrain(World world, Random rand, Block[] BLOCK, byte[] BYTE, int x, int z, double p_150560_7_) { boolean flag = true; Block block = this.topBlock; byte b0 = (byte)(this.field_150604_aj & 255); Block block1 = this.fillerBlock; int k = -1; int l = (int)(p_150560_7_ / 3.0D + 3.0D + rand.nextDouble() * 0.25D); int i1 = x & 15; int j1 = z & 15; int k1 = BLOCK.length / 256; for (int l1 = 255; l1 >= 0; --l1) { int i2 = (j1 * 16 + i1) * k1 + l1; if (l1 <= 0 + rand.nextInt(5)) { //le bloc a la couche 0 BLOCK[i2] = Blocks.bedrock; } else { Block block2 = BLOCK[i2]; if (block2 != null && block2.getMaterial() != Material.air) { //le bloc dans le sol if (block2 == Blocks.stone) { if (k == -1) { if (l <= 0) { block = null; b0 = 0; //le bloc dans le sol block1 = Blocks.stone; } else if (l1 >= 59 && l1 <= 64) { block = this.topBlock; b0 = (byte)(this.field_150604_aj & 255); block1 = this.fillerBlock; } if (l1 < 63 && (block == null || block.getMaterial() == Material.air)) { if (this.getFloatTemperature(x, l1, z) < 0.15F) { } else { } } k = l; if (l1 >= 62) { BLOCK[i2] = block; BYTE[i2] = b0; } else if (l1 < 56 - l) { block = null; block1 = Blocks.stone;//le bloc dans le sol BLOCK[i2] = Blocks.stone;//le bloc dans le sol } else { BLOCK[i2] = block1; } } else if (k > 0) { --k; BLOCK[i2] = block1; if (k == 0 && block1 == Blocks.stone)//le bloc dans le sol { k = rand.nextInt(4) + Math.max(0, l1 - 63); block1 = Blocks.stone;//le bloc dans le sol } } } } else { k = -1; } } } }
Le code est commenté, mais il n’est pas explicable, vous pouvez toujours changer les blocs.
Voilà nous en avons fini avec la classe du biome.La classe du biome montagne :
Cette classe est relativement même. Ajouter en extends Votre premier Biome. Puis ajoutez ça :
private boolean field_150614_aC; public MegaMountainBiomes(int par1, boolean par2) { super(par1, par2); this.topBlock = Blocks.grass; this.fillerBlock = Blocks.dirt; this.theBiomeDecorator.treesPerChunk = 1; this.field_150614_aC = par2; if (par2) { this.theBiomeDecorator.treesPerChunk = 1; } else { this.theBiomeDecorator.treesPerChunk = 2; } }
Cette fonction est très similaire à l’autre classe, sauf que nous avons la génération d’arbre.
Ensuite, ajoutez :
public WorldGenAbstractTree func_150567_a(Random p_150567_1_) { return (WorldGenAbstractTree)(p_150567_1_.nextInt(10) == 0 ? new WorldGenBigTree(false) : (!this.field_150614_aC && p_150567_1_.nextInt(3) == 0 ? new WorldGenTrees(false) : new WorldGenTrees(false))); }
Vous pouvez changer les classes de génération d’arbre, par la classe de votre arbre ou bien d’un autre arbre. Vous l’aurez compris qu’elle (la fonction) permet de générer des arbres.
Ensuite, les deux fonctions sont, les mêmes que dans l’autre classe.
public void genTerrainBlocks(World p_150573_1_, Random p_150573_2_, Block[] p_150573_3_, byte[] p_150573_4_, int p_150573_5_, int p_150573_6_, double p_150573_7_) { this.generateBiomeTerrain(p_150573_1_, p_150573_2_, p_150573_3_, p_150573_4_, p_150573_5_, p_150573_6_, p_150573_7_); } public final void generateBiomeTerrain(World world, Random rand, Block[] BLOCK, byte[] BYTE, int x, int z, double p_150560_7_) { boolean flag = true; Block block = this.topBlock; byte b0 = (byte)(this.field_150604_aj & 255); Block block1 = this.fillerBlock; int k = -1; int l = (int)(p_150560_7_ / 3.0D + 3.0D + rand.nextDouble() * 0.25D); int i1 = x & 15; int j1 = z & 15; int k1 = BLOCK.length / 256; for (int l1 = 255; l1 >= 0; --l1) { int i2 = (j1 * 16 + i1) * k1 + l1; if (l1 <= 0 + rand.nextInt(5)) { BLOCK[i2] = Blocks.bedrock; } else { Block block2 = BLOCK[i2]; if (block2 != null && block2.getMaterial() != Material.air) { if (block2 == Blocks.stone) { if (k == -1) { if (l <= 0) { block = null; b0 = 0; block1 = Blocks.stone; } else if (l1 >= 59 && l1 <= 64) { block = this.topBlock; b0 = (byte)(this.field_150604_aj & 255); block1 = this.fillerBlock; } if (l1 < 63 && (block == null || block.getMaterial() == Material.air)) { if (this.getFloatTemperature(x, l1, z) < 0.15F) { } else { } } k = l; if (l1 >= 62) { BLOCK[i2] = block; BYTE[i2] = b0; } else if (l1 < 56 - l) { block = null; block1 = Blocks.stone; BLOCK[i2] = Blocks.stone; } else { BLOCK[i2] = block1; } } else if (k > 0) { --k; BLOCK[i2] = block1; if (k == 0 && block1 == Blocks.stone) { k = rand.nextInt(4) + Math.max(0, l1 - 63); block1 = Blocks.stone; } } } } else { k = -1; } } } }
Donc je ne pense pas avoir besoin de vous expliquer le tout.
S’il vous reste des erreurs regardez ce que vous avez changé pour vos classes, si vous avez un crash à cause des biomes, regardez si les autres biomes ont le bon extends.
Ce tutoriel est fini, je vous laisse avec le résultat.
Résultat
Le code final :
Classe Principale :
package common.fr.diangle.tutoBiome; import java.util.Random; import common.fr.diangle.tuto.CommonProxy; import net.minecraft.block.Block; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.chunk.IChunkProvider; import net.minecraftforge.common.BiomeDictionary; import cpw.mods.fml.common.IWorldGenerator; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.registry.GameRegistry; @Mod(modid = "tutoworld", version = "1.0", name = "Tutoriel Minecraft Forge France") public class ModTutorielWorldType { public static final String MODID = "tutoworld"; @Instance("tutoworld") public static ModTutorielWorldType instance; @SidedProxy(clientSide = "common.fr.diangle.tuto.ClientProxy", serverSide = "common.fr.diangle.tuto.CommonProxy") public static CommonProxy proxy; @EventHandler public void preInit(FMLPreInitializationEvent event) { } @EventHandler public void init(FMLInitializationEvent event) { BiomeListTuto.BiomeList(); } @EventHandler public void postInit(FMLPostInitializationEvent envent) { BiomeListTuto.worldTypeTuto = new WorldTypeTuto(); } }
La classe des biomes :
package common.fr.diangle.tutoBiome; import net.minecraft.world.biome.BiomeGenBase; public class BiomeListTuto { public static WorldTypeTuto worldTypeTuto; public static BiomeGenBase tutoStonePlains, tutoMegaMountain; protected static final BiomeGenBase.Height height_MidHills = new BiomeGenBase.Height(1.6F, 0.9F); protected static final BiomeGenBase.Height height_LowPlains = new BiomeGenBase.Height(0.125F, 0.03F); public static void BiomeList() { tutoStonePlains = new StonePlainsBiomes(50, true).setBiomeName("Stone Plains").setHeight(height_LowPlains).setTemperatureRainfall(0.8F, 0.4F); tutoMegaMountain = new MegaMountainBiomes(51, true).setBiomeName("Mega Mountain").setHeight(height_MidHills).setTemperatureRainfall(0.2F, 0.3F); } }
La classe World Type :
package common.fr.diangle.tutoBiome; import net.minecraft.world.World; import net.minecraft.world.WorldType; import net.minecraft.world.biome.WorldChunkManager; import net.minecraft.world.gen.layer.GenLayer; import net.minecraft.world.gen.layer.GenLayerBiomeEdge; import net.minecraft.world.gen.layer.GenLayerZoom; import net.minecraftforge.common.DimensionManager; public class WorldTypeTuto extends WorldType { public WorldTypeTuto() { super("tuto"); DimensionManager.unregisterProviderType(0); DimensionManager.registerProviderType(0, WorldProviderTuto.class, true); } public GenLayer getBiomeLayer(long worldSeed, GenLayer parentLayer) { GenLayer ret = new BiomeGenLayerTuto(200L, parentLayer); ret = GenLayerZoom.magnify(1000L, ret, 2); ret = new GenLayerBiomeEdge(1000L, ret); return ret; } public WorldChunkManager getChunkManager(World world) { return new WorldChunkManagerTuto(world); } }
La classe WorldProvider :
package common.fr.diangle.tutoBiome; import net.minecraft.init.Blocks; import net.minecraft.world.WorldProviderSurface; public class WorldProviderTuto extends WorldProviderSurface { public boolean canCoordinateBeSpawn(int par1, int par2) { return this.worldObj.getTopBlock(par1, par2) == Blocks.grass || this.worldObj.getTopBlock(par1, par2) == Blocks.sand || this.worldObj.getTopBlock(par1, par2) == Blocks.stone || this.worldObj.getTopBlock(par1, par2) == Blocks.snow_layer; } public String getDimensionName() { return "tuto"; } }
La classe BiomeGenLayer :
package common.fr.diangle.tutoBiome; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.gen.layer.GenLayer; import net.minecraft.world.gen.layer.IntCache; public class BiomeGenLayerTuto extends GenLayer { protected BiomeGenBase[] baseBiomes = {BiomeListTuto.tutoStonePlains, BiomeListTuto.tutoMegaMountain}; public BiomeGenLayerTuto(long seed, GenLayer genlayer) { super(seed); this.parent = genlayer; } public BiomeGenLayerTuto(long seed) { super(seed); } @Override public int[] getInts(int x, int z, int width, int depth) { int[] dest = IntCache.getIntCache(width * depth); for(int dz = 0; dz < depth; dz++) { for(int dx = 0; dx < width; dx++) { this.initChunkSeed(dx + x, dz + z); dest[(dx + dz * width)] = this.baseBiomes[nextInt(this.baseBiomes.length)].biomeID; } } return dest; } }
La classe GenLayer :
package common.fr.diangle.tutoBiome; import net.minecraft.world.gen.layer.GenLayer; import net.minecraft.world.gen.layer.GenLayerVoronoiZoom; import net.minecraft.world.gen.layer.GenLayerZoom; public abstract class GenLayerTuto extends GenLayer { public GenLayerTuto(long seed) { super(seed); } public static GenLayer[] makeTheWorld(long seed) { GenLayer biomes = new BiomeGenLayerTuto(1L); biomes = new GenLayerZoom(1000L, biomes); biomes = new GenLayerZoom(1001L, biomes); biomes = new GenLayerZoom(1002L, biomes); biomes = new GenLayerZoom(1003L, biomes); biomes = new GenLayerZoom(1004L, biomes); biomes = new GenLayerZoom(1005L, biomes); GenLayer genlayervoronoizoom = new GenLayerVoronoiZoom(10L, biomes); biomes.initWorldGenSeed(seed); genlayervoronoizoom.initWorldGenSeed(seed); return new GenLayer[] {biomes, genlayervoronoizoom}; } }
La classe WorldChunkManager :
package common.fr.diangle.tutoBiome; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraft.world.WorldType; import net.minecraft.world.biome.BiomeCache; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.biome.WorldChunkManager; import net.minecraft.world.gen.layer.GenLayer; import net.minecraft.world.gen.layer.IntCache; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class WorldChunkManagerTuto extends WorldChunkManager { private GenLayer myGenBiomes; private GenLayer myBiomeIndexLayer; private BiomeCache myBiomeCache; private List <biomegenbase>myBiomesToSpawnIn; public WorldChunkManagerTuto() { this.myBiomeCache = new BiomeCache(this); this.myBiomesToSpawnIn = new ArrayList<biomegenbase>(); this.myBiomesToSpawnIn.add(BiomeListTuto.tutoStonePlains); } public WorldChunkManagerTuto(long seed, WorldType worldtype) { this(); GenLayer[] agenlayer = GenLayerTuto.makeTheWorld(seed); this.myGenBiomes = agenlayer[0]; this.myBiomeIndexLayer = agenlayer[1]; } public WorldChunkManagerTuto(World world) { this(world.getSeed(), world.provider.terrainType); } public List <biomegenbase>getBiomesToSpawnIn() { return this.myBiomesToSpawnIn; } public BiomeGenBase getBiomeGenAt(int x, int z) { BiomeGenBase biome = this.myBiomeCache.getBiomeGenAt(x, z); if(biome == null) { return BiomeListTuto.tutoStonePlains; } return biome; } public float[] getRainfall(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5) { if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5) { par1ArrayOfFloat = new float[par4 * par5]; } Arrays.fill(par1ArrayOfFloat, 0, par4 * par5, 0.0F); return par1ArrayOfFloat; } @SideOnly(Side.CLIENT) public float getTemperatureAtHeight(float par1, int par2) { return par1; } public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5) { IntCache.resetIntCache(); if(par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5) { par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5]; } int[] aint = this.myGenBiomes.getInts(par2, par3, par4, par5); for(int i = 0; i < par4 * par5; ++i) { if(aint* >= 0) { par1ArrayOfBiomeGenBase* = BiomeGenBase.getBiome(aint*); } else { par1ArrayOfBiomeGenBase* = BiomeListTuto.tutoStonePlains; } } return par1ArrayOfBiomeGenBase; } public BiomeGenBase[] loadBlockGeneratorData(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5) { return this.getBiomeGenAt(par1ArrayOfBiomeGenBase, par2, par3, par4, par5, true); } public BiomeGenBase[] getBiomeGenAt(BiomeGenBase[] par1ArrayOfBiomeGenBase, int x, int y, int width, int length, boolean cacheFlag) { IntCache.resetIntCache(); if(par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < width * length) { par1ArrayOfBiomeGenBase = new BiomeGenBase[width * length]; } if(cacheFlag && width == 16 && length == 16 && (x & 15) == 0 && (y & 15) == 0) { BiomeGenBase[] abiomegenbase1 = this.myBiomeCache.getCachedBiomes(x, y); System.arraycopy(abiomegenbase1, 0, par1ArrayOfBiomeGenBase, 0, width * length); return par1ArrayOfBiomeGenBase; } else { int[] aint = this.myBiomeIndexLayer.getInts(x, y, width, length); for(int i = 0; i < width * length; ++i) { if(aint* >= 0) { par1ArrayOfBiomeGenBase* = BiomeGenBase.getBiome(aint*); } else { par1ArrayOfBiomeGenBase* = BiomeListTuto.tutoStonePlains; } } return par1ArrayOfBiomeGenBase; } } public boolean areBiomesViable(int par1, int par2, int par3, List par4List) { IntCache.resetIntCache(); int l = par1 - par3 >> 2; int i1 = par2 - par3 >> 2; int j1 = par1 + par3 >> 2; int k1 = par2 + par3 >> 2; int l1 = j1 - l + 1; int i2 = k1 - i1 + 1; int[] aint = this.myGenBiomes.getInts(l, i1, l1, i2); for(int j2 = 0; j2 < l1 * i2; ++j2) { BiomeGenBase biomegenbase = BiomeGenBase.getBiome(aint[j2]); if(!par4List.contains(biomegenbase)) { return false; } } return true; } public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, Random par5Random) { IntCache.resetIntCache(); int l = par1 - par3 >> 2; int i1 = par2 - par3 >> 2; int j1 = par1 + par3 >> 2; int k1 = par2 + par3 >> 2; int l1 = j1 - l + 1; int i2 = k1 - i1 + 1; int[] aint = this.myGenBiomes.getInts(l, i1, l1, i2); ChunkPosition chunkposition = null; int j2 = 0; for(int k2 = 0; k2 < l1 * i2; ++k2) { int l2 = l + k2 % l1 << 2; int i3 = i1 + k2 / l1 << 2; BiomeGenBase biomegenbase = BiomeGenBase.getBiome(aint[k2]); if(par4List.contains(biomegenbase) && (chunkposition == null || par5Random.nextInt(j2 + 1) == 0)) { chunkposition = new ChunkPosition(l2, 0, i3); ++j2; } } return chunkposition; } public void cleanupCache() { this.myBiomeCache.cleanupCache(); } }
Le fichier .lang :
generator.tuto=Tuto World
La classe du biomePlains :
package common.fr.diangle.tutoBiome; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.gen.feature.WorldGenAbstractTree; import net.minecraft.world.gen.feature.WorldGenBigTree; import net.minecraft.world.gen.feature.WorldGenTrees; public class StonePlainsBiomes extends BiomeGenBase { private boolean field_150614_aC; public StonePlainsBiomes(int par1, boolean p_i45379_2_) { super(par1); this.topBlock = Blocks.stone; this.fillerBlock = Blocks.stone; this.field_150614_aC = p_i45379_2_; } public void genTerrainBlocks(World p_150573_1_, Random p_150573_2_, Block[] p_150573_3_, byte[] p_150573_4_, int p_150573_5_, int p_150573_6_, double p_150573_7_) { this.generateBiomeTerrain(p_150573_1_, p_150573_2_, p_150573_3_, p_150573_4_, p_150573_5_, p_150573_6_, p_150573_7_); } public void generateBiomeTerrain(World world, Random rand, Block[] BLOCK, byte[] BYTE, int x, int z, double p_150560_7_) { boolean flag = true; Block block = this.topBlock; byte b0 = (byte)(this.field_150604_aj & 255); Block block1 = this.fillerBlock; int k = -1; int l = (int)(p_150560_7_ / 3.0D + 3.0D + rand.nextDouble() * 0.25D); int i1 = x & 15; int j1 = z & 15; int k1 = BLOCK.length / 256; for (int l1 = 255; l1 >= 0; --l1) { int i2 = (j1 * 16 + i1) * k1 + l1; if (l1 <= 0 + rand.nextInt(5)) { //le bloc a la couche 0 BLOCK[i2] = Blocks.bedrock; } else { Block block2 = BLOCK[i2]; if (block2 != null && block2.getMaterial() != Material.air) { //le bloc dans le sol if (block2 == Blocks.stone) { if (k == -1) { if (l <= 0) { block = null; b0 = 0; //le bloc dans le sol block1 = Blocks.stone; } else if (l1 >= 59 && l1 <= 64) { block = this.topBlock; b0 = (byte)(this.field_150604_aj & 255); block1 = this.fillerBlock; } if (l1 < 63 && (block == null || block.getMaterial() == Material.air)) { if (this.getFloatTemperature(x, l1, z) < 0.15F) { } else { } } k = l; if (l1 >= 62) { BLOCK[i2] = block; BYTE[i2] = b0; } else if (l1 < 56 - l) { block = null; block1 = Blocks.stone;//le bloc dans le sol BLOCK[i2] = Blocks.stone;//le bloc dans le sol } else { BLOCK[i2] = block1; } } else if (k > 0) { --k; BLOCK[i2] = block1; if (k == 0 && block1 == Blocks.stone)//le bloc dans le sol { k = rand.nextInt(4) + Math.max(0, l1 - 63); block1 = Blocks.stone;//le bloc dans le sol } } } } else { k = -1; } } } } }
La classe du biome montagne :
package common.fr.diangle.tutoBiome; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.gen.feature.WorldGenAbstractTree; import net.minecraft.world.gen.feature.WorldGenBigTree; import net.minecraft.world.gen.feature.WorldGenTrees; public class MegaMountainBiomes extends StonePlainsBiomes { private boolean field_150614_aC; public MegaMountainBiomes(int par1, boolean par2) { super(par1, par2); this.topBlock = Blocks.grass; this.fillerBlock = Blocks.dirt; this.theBiomeDecorator.treesPerChunk = 1; this.field_150614_aC = par2; if (par2) { this.theBiomeDecorator.treesPerChunk = 1; } else { this.theBiomeDecorator.treesPerChunk = 2; } } public WorldGenAbstractTree func_150567_a(Random p_150567_1_) { return (WorldGenAbstractTree)(p_150567_1_.nextInt(10) == 0 ? new WorldGenBigTree(false) : (!this.field_150614_aC && p_150567_1_.nextInt(3) == 0 ? new WorldGenTrees(false) : new WorldGenTrees(false))); } public void genTerrainBlocks(World p_150573_1_, Random p_150573_2_, Block[] p_150573_3_, byte[] p_150573_4_, int p_150573_5_, int p_150573_6_, double p_150573_7_) { this.generateBiomeTerrain(p_150573_1_, p_150573_2_, p_150573_3_, p_150573_4_, p_150573_5_, p_150573_6_, p_150573_7_); } public final void generateBiomeTerrain(World world, Random rand, Block[] BLOCK, byte[] BYTE, int x, int z, double p_150560_7_) { boolean flag = true; Block block = this.topBlock; byte b0 = (byte)(this.field_150604_aj & 255); Block block1 = this.fillerBlock; int k = -1; int l = (int)(p_150560_7_ / 3.0D + 3.0D + rand.nextDouble() * 0.25D); int i1 = x & 15; int j1 = z & 15; int k1 = BLOCK.length / 256; for (int l1 = 255; l1 >= 0; --l1) { int i2 = (j1 * 16 + i1) * k1 + l1; if (l1 <= 0 + rand.nextInt(5)) { BLOCK[i2] = Blocks.bedrock; } else { Block block2 = BLOCK[i2]; if (block2 != null && block2.getMaterial() != Material.air) { if (block2 == Blocks.stone) { if (k == -1) { if (l <= 0) { block = null; b0 = 0; block1 = Blocks.stone; } else if (l1 >= 59 && l1 <= 64) { block = this.topBlock; b0 = (byte)(this.field_150604_aj & 255); block1 = this.fillerBlock; } if (l1 < 63 && (block == null || block.getMaterial() == Material.air)) { if (this.getFloatTemperature(x, l1, z) < 0.15F) { } else { } } k = l; if (l1 >= 62) { BLOCK[i2] = block; BYTE[i2] = b0; } else if (l1 < 56 - l) { block = null; block1 = Blocks.stone; BLOCK[i2] = Blocks.stone; } else { BLOCK[i2] = block1; } } else if (k > 0) { --k; BLOCK[i2] = block1; if (k == 0 && block1 == Blocks.stone) { k = rand.nextInt(4) + Math.max(0, l1 - 63); block1 = Blocks.stone; } } } } else { k = -1; } } } } }
Crédit
Rédaction :
Correction :
Ce tutoriel de Minecraft Forge France est mis à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International
-
donc voilà selon moi le tutoriel est fini, je demanderai au modérateur et administrateur de regarder, et de permettre au correcteur de corrigé, je passerais aussi corrigé après (avant les correcteur), si il manque quelque chose merci de me le signaler.
-
Personnelement, je trouves que c’est un très bon tutoriel !
Il ne te reste plus qu’a en faire un sur la génération de structures et tu auras fait le tour ! ^^Continues comme cela, tes tutos sont bien (sauf (oui je suis chiant là-dessus) au niveau de l’orthographe mais heuresement, il y a les correcteurs qui vont bientôt passer ! )
-
@‘bbcmh3’:
Personnelement, je trouves que c’est un très bon tutoriel !
Il ne te reste plus qu’a en faire un sur la génération de structures et tu auras fait le tour ! ^^Continues comme cela, tes tutos sont bien (sauf (oui je suis chiant là-dessus) au niveau de l’orthographe mais heuresement, il y a les correcteurs qui vont bientôt passer ! )
Je vais regarder pour les structures, mais je crois que elle se génère ^^, sinon merci.
Au moins il y a quelqu’un qui lit mes tuto et me donne des retours ^^. -
Je suis sur que beaucoup de personnes lisent tes tutos ne dis pas ça ! ;D
Bah ça m’a aidé donc je ne vais pas dire le contraire non plus, hein ! ^^ -
Donc voilà le tutoriel est fini, j’aimerais bien que les modo et admin valide se tuto et permette au correcteur de corrigé.
-
J’ai corrigé le tuto.
-
0 FPS ? xD
-
@‘AlphaSwittleTeam’:
0 FPS ? xD
De ?
-
Sur un screenshot il y a 0fps.
-
ha oui ^^.
-
Ho ! Je savais pas que le tuto étais ici, j’en ai aussi profiter pour mettre le résultat (images) dans une infobulle.
-
J’ai essayé de generer mon propre arbre dans mon World Type mais sans succès ! J’ai rajouté ceci a mon code :
public WorldGenAbstractTree func_150567_a(Random p_150567_1_) { return (WorldGenAbstractTree)(p_150567_1_.nextInt(10) == 0 ? new WorldGenAncientAcacia(false) : (!this.field_150614_aC && p_150567_1_.nextInt(3) == 0 ? new WorldGenTrees(false) : new WorldGenTrees(false))); } public void genTerrainBlocks(World p_150573_1_, Random p_150573_2_, Block[] p_150573_3_, byte[] p_150573_4_, int p_150573_5_, int p_150573_6_, double p_150573_7_) { this.generateBiomeTerrain(p_150573_1_, p_150573_2_, p_150573_3_, p_150573_4_, p_150573_5_, p_150573_6_, p_150573_7_); } public final void generateBiomeTerrain(World world, Random rand, Block[] BLOCK, byte[] BYTE, int x, int z, double p_150560_7_) { boolean flag = true; Block block = this.topBlock; byte b0 = (byte)(this.field_150604_aj & 255); Block block1 = this.fillerBlock; int k = -1; int l = (int)(p_150560_7_ / 3.0D + 3.0D + rand.nextDouble() * 0.25D); int i1 = x & 15; int j1 = z & 15; int k1 = BLOCK.length / 256; for (int l1 = 255; l1 >= 0; –l1) { int i2 = (j1 * 16 + i1) * k1 + l1; if (l1 <= 0 + rand.nextInt(5)) { BLOCK[i2] = Blocks.bedrock; } else { Block block2 = BLOCK[i2]; if (block2 != null && block2.getMaterial() != Material.air) { if (block2 == Blocks.stone) { if (k == -1) { if (l <= 0) { block = null; b0 = 0; block1 = Blocks.stone; } else if (l1 >= 59 && l1 <= 64) { block = this.topBlock; b0 = (byte)(this.field_150604_aj & 255); block1 = this.fillerBlock; } if (l1 < 63 && (block == null || block.getMaterial() == Material.air)) { if (this.getFloatTemperature(x, l1, z) < 0.15F) { } else { } } k = l; if (l1 >= 62) { BLOCK[i2] = block; BYTE[i2] = b0; } else if (l1 < 56 - l) { block = null; block1 = Blocks.stone; BLOCK[i2] = Blocks.stone; } else { BLOCK[i2] = block1; } } else if (k > 0) { –k; BLOCK[i2] = block1; if (k == 0 && block1 == Blocks.stone) { k = rand.nextInt(4) + Math.max(0, l1 - 63); block1 = Blocks.stone; } } } } else { k = -1; } } } }
Ah cette ligne :
return (WorldGenAbstractTree)(p_150567_1_.nextInt(10) == 0 ? new WorldGenAncientAcacia(false) : (!this.field_150614_aC && p_150567_1_.nextInt(3) == 0 ? new WorldGenTrees(false) : new WorldGenTrees(false)));
field_150614_aC est surligner en rouge . . .
Mais je ne comprend pas le code donc je n’arrive pas a résoudre le soucis /:
-
Les arbres vont dans les biomes, ou tu peux générer la structure comme une autre structure. (vas voir le tuto des arbres).
-
Salut, merci d’avoir fait ce super tutoriel qui m’a beaucoup aidé, mais j’ai 2 questions:
lorsque je mets ça :
:::
public Paradis(int par1, boolean par2)
{
super(par1);this.topBlock = MineplusPrincipale.Paradise_Dirt;
this.fillerBlock = MineplusPrincipale.Paradise_Stone;
this.theBiomeDecorator.treesPerChunk = 3;
this.field_150614_aC = par2;if (par2)
{
this.theBiomeDecorator.treesPerChunk = 4;
}
else
{
this.theBiomeDecorator.treesPerChunk = 5;
}
}
:::dans ma classe du biome, l’effet topblock et fillerblock ne sont pas pris en compte
Pourtant les blocks existe dans le jeu et son bien enregistrés.Et deuxième question, connais tu un moyen pour faire que la dimension soit accesible en aventure survie(portail, item spécial ect)
Merci d’avance
-
1ere solution, tu as créé la fonction de génération ? Ensuite je ne vois pas.
-
Oui toutes les classe sont faites sauf GenLayer où a ces lignes la :
public GenLayerTuto(long seed)
{
super(seed);
}je ne peux pas écrire seed car on m’affiche une erreur
-
envoi moi toute les classes avec les balise java.
-
Merci Diangle de ton tuto, il est bien expliquer et j’ai donc réussi a faire mon tout premier biome mais il y a quelque chose que je loupe
ou comprend pas :
C’est comment faire spawn le biome normalement car j’ai chercher longtemps sur plusieur world que j’ai générer et je ne les pas trouver.
Le seul endroit ou je les générer c’est avec l’option dans les parametres avancée et apres il est partout, il n’y a que lui de générer.
Merci de ta reponse -
@‘Themoderne76133’:
Merci Diangle de ton tuto, il est bien expliquer et j’ai donc réussi a faire mon tout premier biome mais il y a quelque chose que je loupe
ou comprend pas :
C’est comment faire spawn le biome normalement car j’ai chercher longtemps sur plusieur world que j’ai générer et je ne les pas trouver.
Le seul endroit ou je les générer c’est avec l’option dans les parametres avancée et apres il est partout, il n’y a que lui de générer.
Merci de ta reponsedans les dernière version de forge tu as moyen de faire spawn ton biome naturellement, dans les versions plus ancienne faut passer par le world type ^^