Génération procédurale de minerais.


Categorie : Commandes

Poster le : 2020-02-16 21:25:06 par

Hardel

Bonjour, dans ce tutoriel nous allons voir comment faire de la génération procédurale de minerais dans n'importe quelle dimension. Et ce, simplement, rapidement, et facilement tout en restant optimisé.

Pour commencer, qu'est-ce que la génération procédurale ? Pour faire simple c'est le fait de faire apparaître, selon un pattern défini, une structure comme des arbres, des biomes, des minerais, ou encore des structures, et ce de façon aléatoire et logique dans le jeu. À noter que plus la génération procédurale est bien codée, plus l'immersion est augmentée.
 
Il s'agit d'un élément fondamental de Minecraft. Tout ce que votre monde a généré est généré de manière procédurale.
 
Cette méthode n'est pas vraiment destinée pour les datapacks, mais l'est plus pour les mods, car la quantité de ressources qu'elle demande est phénoménale.
 Néanmoins elle est largement faisable en ce que concerne la génération de deux/trois blocs, en dépit du peu de puissance requise.

Pour commencer il nous faut un Datapack.  (Si vous n’êtes pas à l’aise avec les datapacks, et leurs fonctionnements je vous redirige vers un autre article qui en parlera en profondeur. (Bientôt).)

Instanciez donc votre datapack avec le nom de votre choix et insérez-y un dossier "data" puis un sous dossier qui sera votre espace de travail (vous pouvez lui donner le nom que vous souhaitez). 

Rappel : Pas de majuscule sur les noms de dossiers et de fichiers car cela peut poser des problèmes lors du chargement et donc ne pas fonctionner.

Ensuite, créez un répertoire "function" dans lequel vous placerez un dossier "generation".

Vous devriez logiquement vous retrouver avec ça:

(C'est important de toujours bien ranger les choses en programmation, puisque cela permet de mieux s'y retrouver quand on revient sur notre travail, après plusieurs mois.)

On va maintenant revenir dans l'arborescence :

 Dans le dossier "data" créons le dossier "minecraft" qui nous permettra de modifier les données de base du jeu. Puis créons un dossier "loot_tables" qui sera suivi du répertoire "blocks" et dans lequel nous créerons le fichier "spawner.json" (on reviendra dessus plus tard dans le guide, mais retenez simplement qu'il nous servira à modifier le butin que l'on obtiendra en cassant ce bloc).

On utilisera un spawner avec une texture par dessus, car les spawner classiques ne nous donneront jamais quelque chose.

Revenons dans le dossier "minecraft".

Ajoutez-y "tags" et dedans "function". Instanciez les fichiers "load.json" et "tick.json" à l'intérieur, pour ensuite les ouvrir dans votre éditeur de fichier favori. 

Les fichiers "load.json" et "tick.json" permettent de cibler un ou plusieurs fichier(s) ".mcfunction", et de leur attribuer une propriété spéciale.

(En effet, toutes les fonctions contenues dans "load.json" sont exécutée une seule fois, au (re)chargement du datapack, ce qui permet généralement d'initier des tableaux de scores (scoreboard), des espaces de stockage (data storage), des équipes (team), mais aussi aussi des messages (tellraw, title, ...) pour s'assurer que le datapack fonctionne correctement. Les fonctions du "tick.json" s'exécuteront quant à elles à chaque TPS (Tick per seconds), donnant lieu à 20 exécutions chaque secondes (car 1 seconde est égale à 20 Tps dans Minecraft).)

// Fichier tick.json
{
    "replace": false,
    "values": [
      "magic:main"
    ]
 }

// Fichier load.json
{
    "replace": false,
    "values": [
      "magic:load"
    ]
 }

Dans "magic:main" ou "magic:load", le mot "magic" représente le répertoire de travail du datapack. Tandis que "main" et "load" réfèrent à des fonctions contenues dans ce dossier.
Et ce sont justement eux que nous allons éditer dès maintenant !

Commençons par "Load" on va venir créer les Scoreboard et les Variables.

 # On affiche à toutes les personnes en mode créatif que le datapack s'est lancé/démarré avec succès.
tellraw @a[gamemode=creative] ["",{"text":"[Magic] ","color":"red"},{"text":"is ready !","color":"green"}]
# On désactive les messages de réussite de commande.
gamerule commandBlockOutput false
 
# On créer les tableaux de scores qui nous servirons pour la suite.
scoreboard objectives add TimerChunck minecraft.custom:minecraft.play_one_minute
scoreboard objectives add ChunckRandom dummy
scoreboard objectives add OreCount dummy
scoreboard objectives add Memory dummy
scoreboard objectives add ChunckValue dummy
# Ici on définit sur quelle couche le minerais apparaît et en quelle quantité il apparaîtra par tronçons (=chunks) dans leu
# /!\ le Y_Max c'est le Y_Min + Y_Max (dans mon cas mon minerais apparaît de la couche 5 a 17).
scoreboard players set #Terrariuem_Y_Min ChunckValue 5
scoreboard players set #Terrariuem_Y_Max ChunckValue 12
scoreboard players set #Terrariuem_Count ChunckValue 1
scoreboard players set #16 ChunckValue 16

Le type "PlayOnMinute" va venir augmenter le score de 1 de tout les joueurs chaque ticks.

Maintenant éditons le fichier "main"  et c'est ce dernier qui s'exécutera à chaque TPS du jeu.

Nous allons donc y mettre cette commande :

execute as @a[scores={TimerChunck=200..}] at @s run function magic:generation/check_chunck

Cette commande va regarder si le compteur "TimerChunck" du joueur est à 200 ticks (soit 10 secondes, 200t/20=10s), et va alors lancer la génération sur les-dits joueurs.


On en est enfin prêt a  travailler correctement :

Maintenant revenons dans le dossier "generation", on va enfin commencer à coder ! Créons notre premier fichier "check_chunck.mcfunction" qui vérifiera si le chunck n'a pas déjà été modifié.

# On met le Timer "TimerChuck" du joueur à 0.
scoreboard players set @s TimerChunck 0
# On invoque une AEC (AreaEffecCloud), avec le tag 'Chunck', qui ne dure que 0.5 secondes.
summon minecraft:area_effect_cloud ~ ~ ~ {Duration:10,Tags:["Chunck"]}
# On effectue sur toutes les AEC, la vérification de chunck.
execute as @e[tag=Chunck,sort=nearest,limit=1] at @s run function magic:generation/pos
# Selon la dimension on effectueras une génération adapté.
execute if entity @s[nbt={Dimension:-1}] as @e[tag=Chunck,sort=nearest,limit=1] at @s run function magic:generation/nether/core
execute if entity @s[nbt={Dimension:0}] as @e[tag=Chunck,sort=nearest,limit=1] at @s run function magic:generation/overworld/core
execute if entity @s[nbt={Dimension:1}] as @e[tag=Chunck,sort=nearest,limit=1] at @s run function magic:generation/end/core

Puis on va créer la function "pos.mcfunction"  qui va positionner l'AEC en bordure de son chunck et en Y = 0.

execute store result entity @s Pos[0] double 16 run data get entity @s Pos[0] 0.0625
execute store result entity @s Pos[1] double 1 run data get entity @s Age 0
execute store result entity @s Pos[2] double 16 run data get entity @s Pos[2] 0.0625

Maintenant, on va créer trois dossiers, un pour"overworld, un pour le Nether et un pour L'end, le contenue serra quasiment identique, ici nous ferons que l'overworld.

Rendons dans ce dossier, et on va créer 3 fichiers : "check", "core" et "next_chunck", on va aussi créer un dossier par minerais, ici je n'ai que le "Terrarium" donc je créer un dossier que j'appelle "Terrarium", et dedans il auras aussi trois fichiers. "count",  "place" et "random_pos".

Voici donc ce que cela devrait vous donner :


Le fichier "core", c'est celui qui va gérer les chunck, Modifions le maintenant, 

Concrètement pour détecter si un chunck a déjà était modifier ou non on va venir retirer sa bedrock a sont point 0, 0, 0, et en placer une en 0, 1, 0 pour éviter que le joueurs puisse trouver du vide.

Si il n'a pas de bedrock, il a était modifiers, Sinon il n'a pas était modifier.

# Si le chunck n'a pas étais modifiers alors on le modifie. execute if block ~ ~ ~ minecraft:bedrock run function magic:generation/overworld/check
# On va venir regarder les chunck au alentours.
execute at @s[tag=Chunck] run function magic:generation/overworld/next_chunck

Le fichier "Next_chunck" étant très gros il vous serra donner sous forme d'image, il permet de faire apparaitre une AEC sur tout les chunck aux alentours.

On fait cela parce que si le joueurs explore une caverne il ne doit pas voire apparaître comme par magie le minerais sous ces yeux.

Et voici le contenue du premiers fichier "check".

# On venir supprimer la bedrock, et le déplacer juste au dessus, Si un blocs d'air est 
présent en bordure de sont chunck c'est que le chunck a déjà était modifier.
setblock ~ ~ ~ air
setblock ~ 1 ~ bedrock
 
# On récupére le contenue de la variable, TerrariumCount qu'on a définie dans le fichier load, qui contient le nombre d'apparition de notre minerais pas chunck, et ont lance la function le nombre de fois qu'il y'a de  valeur..
scoreboard players operation @s OreCount = #Terrariuem_Count ChunckValue
function magic:generation/overworld/terrarium/count
 
# Grâce a cette function, on va effectuais a toutes les AEC, qui on le Tag terrarium générée par la function au dessus, une modification de leurs coordonnées, on va venir les placer aléatoirement dans le chunck selon les paramètre de "Load.mcfunction".
execute as @e[tag=Terrarium] at @s run function magic:generation/overworld/terrarium/random_pos

Et maintenant on va voir les deux fichiers "count" et "random_pos"

Le fichier "Count" et une boucle, qui se lance x fois, x étant la variables qu'on a définie plutôt  :

# On retire 1 a OreCount a chaque itération
scoreboard players remove @s OreCount 1
# On invoque un Terrarium AEC, ici c'est un AS mais cela fonctionne aussi avec une AEC.
summon minecraft:armor_stand ~ ~ ~ {Tags:["Terrarium"]}
# Si la variable OreCount et supérieurs a 1 alors ont relance cette fonction.
execute if score @s OreCount matches 1.. run function magic:generation/overworld/terrarium/count

Le fichier "random_pos" modifie les coordonnées du minerai mais dans sont propre chunck. 

Il s'agit ici de pas mal de calcul mathématique , je ne vais pas vraiment argumenter ce fichier mais si vous voulez plus d'information demander moi en commentaire.

execute store result score @s Memory run data get entity @s Pos[0]
execute store result score @s ChunckRandom run data get entity @s UUIDLeast 0.00000000023283064
scoreboard players operation @s ChunckRandom %= #16 ChunckValue
scoreboard players operation @s ChunckRandom += @s Memory
execute store result entity @s Pos[0] double 1 run scoreboard players get @s ChunckRandom
 
execute store result score @s ChunckRandom run data get entity @s UUIDLeast 0.00000000023283064
scoreboard players operation @s ChunckRandom %= #Terrariuem_Y_Max ChunckValue
scoreboard players operation @s ChunckRandom += #Terrariuem_Y_Min ChunckValue
execute store result entity @s Pos[1] double 1 run scoreboard players get @s ChunckRandom
 
execute store result score @s Memory run data get entity @s Pos[2]
execute store result score @s ChunckRandom run data get entity @s UUIDMost 0.00000000023283064
scoreboard players operation @s ChunckRandom %= #16 ChunckValue
scoreboard players operation @s ChunckRandom += @s Memory
execute store result entity @s Pos[2] double 1 run scoreboard players get @s ChunckRandom
execute positioned as @s run function magic:generation/overworld/terrarium/place

On voit que le fichier "place" est appelé on va donc voir ce qu'il contient :

Pour faire simple, il permet de placer le minerai, et de définir ce qu'on obtient quand on le mine, il permet aussi de définir la texture du minerais. 

(Ce Guide ne vous montre pas comment créer une texture de bloc, une partie deux portant sur le ressource pack est en préparation.)

fill ~ ~ ~ ~ ~ ~ minecraft:spawner{MaxNearbyEntities:0,RequiredPlayerRange:0,
SpawnData:{id:"minecraft:armor_stand",
ItemsLoot:{CustomModelData:300,Name:'{"text":"Terrarium","color":"aqua"}',OreID:"Terrarium"},
Marker:1b,Invisible:1b,
ArmorItems:[{},{},{},{id:"minecraft:command_block",Count:1b,tag:{CustomModelData:250}}],
Tags:["Terrarium_Ore"]}} replace stone
kill @s

On peut modifier ici plusieurs choses, "CustomModelData" dans le NBT "ArmorItems" correspond a la texture de votre blocs je vous renvoie vers un article qui est actuellement en train d’être écris pour la création de blocs customisé en Datapack.

Le NBT, ItemsLoot c'est l'objets qui serras donner quand ce bloque serras détruit.

Maintenant il nous reste plus qu'un seul fichiers a modifier le "spawners.json", qu'on a créer au débuts de ce guide.

{
    "type": "minecraft:block",
    "pools": [
        {
            "rolls": 1,
            "entries": [
                {
                    "type": "minecraft:item",
                    "name": "minecraft:command_block",
                    "functions": [
                        {
                            "function": "minecraft:copy_nbt",
                            "source": "block_entity",
                            "ops": [
                                {
                                    "source": "SpawnData.ItemsLoot.CustomModeldata",
                                    "target": "CustomModelData",
                                    "op": "replace"
                                },
                                {
                                    "source": "SpawnData.ItemsLoot.Name",
                                    "target": "display.Name",
                                    "op": "replace"
                                },
                                {
                                    "source": "SpawnData.ItemsLoot.OreID",
                                    "target": "OreID",
                                    "op": "replace"
                                }
                            ]
                        }
                    ]
                }
            ],
            "conditions": [
                {
                    "condition": "minecraft:survives_explosion"
                }
            ]
        }
    ]
}

Ce fichiers va gérer l'item qui serras donner quand on va casser le minerais, je ne vais pas trop rentrer dans les détails mais si vous voulez un article parlant plus en détails des fichiers LootTable faite le moi savoir.

Pour simplifier, il va prendre la donnée  "ItemsLoot"  du bloc, est en créer l'items avec.
 
Ce guide est maintenant finie, et tout devrais fonctionner correctement si vous avez des question n'hésiter pas a demander dans les commentaire, une partie deux et en préparation qui va vous permettre de gérer la texture du minerais et de l'afficher.
 
Merci d'avoir pris le temps de lire cette article assez charger et assez long.


Espace commentaire :