[Java] Créons un Minecraft Mod 1.16.1 [Ajouter et générer des arbres]

(Cet article fait partie d'une série d'articles de commentaires)

Premier article: Introduction Article précédent: Ajouter un bloc Article suivant:

Remarques

Jusqu'à présent, nous avons pris le corps des articles continus et supposé que les questions non spécifiées par ailleurs sont les mêmes que précédemment, mais soyez particulièrement prudent car nous avons modifié l'environnement à partir de cet article.

environnement

** Mise à jour de la version de Minecraft Forge. ** C'est parce que c'est une version en cours de développement et qu'il y a de nombreuses parties non développées. Veuillez également noter que la version est toujours en développement après la mise à jour et que des versions mises à jour sont publiées chaque jour.

version
OS Winsows 10 Home
Oracle JDK 8u212
Minecraft 1.16.1
Minecraft Forge 1.16.1 (32.0.108) -> 1.16.1 (33.0.22)
InteliJ IDEA 2020.1.3 (CE)

Ajouter chaque élément de bloc

Ajoutez des journaux, des feuilles et des blocs de semis en vous référant à Ajouter un bloc.

Blocks.java


package jp.koteko.liveinwater.block;

import jp.koteko.liveinwater.LiveInWater;
import jp.koteko.liveinwater.block.trees.WaterTree;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.material.MaterialColor;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.world.FoliageColors;
import net.minecraft.world.biome.BiomeColors;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import java.util.ArrayList;
import java.util.List;

@Mod.EventBusSubscriber(modid = LiveInWater.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Blocks {
    public static List<Block> blockList = new ArrayList<Block>();
    public static Block WATERTREE_ROOT_BLOCK = register("watertree_root_block", new Block(AbstractBlock.Properties.create(Material.WOOD).hardnessAndResistance(2.5F).sound(SoundType.WOOD)));
    public static Block WATERTREE_LOG = register("watertree_log", new RotatedPillarBlock(AbstractBlock.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2.0F).sound(SoundType.WOOD)));
    public static Block WATERTREE_LEAVES = register("watertree_leaves", new LeavesBlock(AbstractBlock.Properties.create(Material.LEAVES).hardnessAndResistance(0.2F).tickRandomly().sound(SoundType.PLANT).notSolid()));
    public static Block WATERTREE_SAPLING = register("watertree_sapling", new SaplingBlock(new WaterTree(), AbstractBlock.Properties.create(Material.PLANTS).doesNotBlockMovement().tickRandomly().zeroHardnessAndResistance().sound(SoundType.PLANT)));

    private static Block register(String key, Block blockIn){
        blockList.add(blockIn);
        return blockIn.setRegistryName(LiveInWater.MOD_ID, key);
    }

    @SubscribeEvent
    public static void registerBlocks(RegistryEvent.Register<Block> event) {
        for (Block block : blockList) {
            event.getRegistry().register(block);
            if (block instanceof SaplingBlock) {
                RenderTypeLookup.setRenderLayer(block, RenderType.getCutout());
            }
        }
    }

    @SubscribeEvent
    public static void registerBlockColors(ColorHandlerEvent.Block event) {
        event.getBlockColors().register((p_210229_0_, p_210229_1_, p_210229_2_, p_210229_3_) -> {
            return p_210229_1_ != null && p_210229_2_ != null ? BiomeColors.getFoliageColor(p_210229_1_, p_210229_2_) : FoliageColors.getDefault();
        }, WATERTREE_LEAVES);
    }
}

Les grumes sont fabriquées dans la classe Rotated Pillar Block, les feuilles sont fabriquées dans la classe Leaves Block et les semis sont fabriqués dans la classe Sapling Block. Les paramètres détaillés sont communs à Block (par exemple, définissez la dureté et la résistance avec .hardnessAndResistance ()), donc modifiez-les si nécessaire. Les valeurs ci-dessus sont (devraient) être des valeurs standard pour chacun. Le premier argument passé au constructeur SaplingBlock est une instance de l'arbre généré par le semis. Je ne l'ai pas encore défini, mais je l'expliquerai plus tard. De plus, une description a été ajoutée à la partie d'enregistrement de bloc. Cela définit le type de rendu afin d'afficher correctement la texture du bloc de semis. Si cela n'est pas fait, la partie qui doit être transparente sera peinte en noir. Référence Enfin, la couleur du bloc de feuilles est réglée pour changer en fonction de la couleur du biome. Depuis que j'ai apporté la description de au 1.14.4 telle quelle, je n'ai pas regardé profondément à l'intérieur. Vous pouvez en voir plus en observant la classe BlockColors. À propos de la couleur du biome [page de référence](https://minecraft-ja.gamepedia.com/%E3%83%90%E3%82%A4%E3%82%AA%E3%83%BC%E3%83% A0 # .E3.83.90.E3.82.A4.E3.82.AA.E3.83.BC.E3.83.A0.E3.82.AB.E3.83.A9.E3.83.BC.E3 .81.AE.E6.B1.BA.E5.AE.9A). Si ce n'est pas défini, la couleur de la texture sera utilisée telle quelle pour tous les biomes et peut être omise.

2020-09-16_22.33.19.png La couleur des feuilles change en fonction du biome (Puisque c'est après mise en œuvre jusqu'à la génération naturelle à la fin de l'article, aucun arbre n'est généré dans le monde à ce stade)


Items.java


package jp.koteko.liveinwater.item;

import jp.koteko.liveinwater.LiveInWater;
import jp.koteko.liveinwater.block.Blocks;
import net.minecraft.block.Block;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import java.util.ArrayList;
import java.util.List;

@Mod.EventBusSubscriber(modid = LiveInWater.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Items {
    public static List<Item> itemList = new ArrayList<Item>();
    public static final Item WATERTREE_ROOT = register("watertree_root", new Item((new Item.Properties()).group(LiwItemGroup.DEFAULT)));
    public static final Item WATERTREE_ROOT_BLOCK = register("watertree_root_block", Blocks.WATERTREE_ROOT_BLOCK, LiwItemGroup.DEFAULT);
    public static final Item WATERTREE_LOG = register("watertree_log", Blocks.WATERTREE_LOG, LiwItemGroup.DEFAULT);
    public static final Item WATERTREE_LEAVES = register("watertree_leaves", Blocks.WATERTREE_LEAVES, LiwItemGroup.DEFAULT);
    public static final Item WATERTREE_SAPLING = register("watertree_sapling", Blocks.WATERTREE_SAPLING, LiwItemGroup.DEFAULT);

    private static Item register(String key, Item itemIn) {
        itemList.add(itemIn);
        return itemIn.setRegistryName(LiveInWater.MOD_ID, key);
    }
    private static Item register(String key, Block blockIn, ItemGroup itemGroupIn) {
        return register(key, new BlockItem(blockIn, (new Item.Properties()).group(itemGroupIn)));
    }

    @SubscribeEvent
    public static void registerItems(RegistryEvent.Register<Item> event) {
        for (Item item : itemList) {
            event.getRegistry().register(item);
        }
    }
}

Déclarez et enregistrez BlockItem. Voir également Ajouter un élément (https://qiita.com/koteko/items/578c3cfdfd7ef71df9c1).


Définissez resources.

\src\main\resources
   ├ assets
   │  └ example_mod
   │     ├ blockstates
   │     │  ├ watertree_leaves.json
   │     │  ├ watertree_log.json
   │     │  └ watertree_sapling.json
   │     ├ lang
   │     │  └ en_us.json
   │     │  └ ja_jp.json
   │     ├ models
   │     │  ├ block
   │     │  │  ├ watertree_leaves.json
   │     │  │  ├ watertree_log.json
   │     │  │  └ watertree_sapling.json
   │     │  └ item
   │     │     ├ example_leaves.json
   │     │     ├ example_log.json
   │     │     └ example_sapling.json
   │     └ textures
   │        ├ block
   │        │  ├ watertree_leaves.json
   │        │  ├ watertree_log.json
   │        │  └ watertree_sapling.json
   │        └ item
   │           └ watertree_sapling.json
   └ data
      └ liveinwater
         └ loot_tables
            └ blocks
               ├ example_leaves.json
               ├ example_log.json
               └ example_sapling.json

blockstates\watertree_leaves.json


{
  "variants": {
    "": { "model": "liveinwater:block/watertree_leaves" }
  }
}

blockstates\watertree_log.json


{
  "variants": {
    "axis=y": { "model": "liveinwater:block/watertree_log" },
    "axis=z": { "model": "liveinwater:block/watertree_log", "x": 90 },
    "axis=x": { "model": "liveinwater:block/watertree_log", "x": 90, "y": 90 }
  }
}

Faites pivoter le modèle en fonction du sens d'installation.

blockstates\watertree_sapling.json


{
  "variants": {
    "": { "model": "liveinwater:block/watertree_sapling" }
  }
}

en_us.jp


{
  "item.liveinwater.watertree_log": "WaterTree Log",
  "item.liveinwater.watertree_leaves": "WaterTree Leaves",
  "item.liveinwater.watertree_sapling": "WaterTree Sapling",
  "block.liveinwater.watertree_log": "WaterTree Log",
  "block.liveinwater.watertree_leaves": "WaterTree Leaves",
  "block.liveinwater.watertree_sapling": "WaterTree Sapling"
}

ja_jp.json


{
  "item.liveinwater.watertree_log": "Journal de l'arbre d'eau",
  "item.liveinwater.watertree_leaves": "Feuilles d'arbre d'eau",
  "item.liveinwater.watertree_sapling": "Arroser les plants d'arbres",
  "block.liveinwater.watertree_log": "Journal de l'arbre d'eau",
  "block.liveinwater.watertree_leaves": "Feuilles d'arbre d'eau",
  "block.liveinwater.watertree_sapling": "Arroser les plants d'arbres"
}

models\block\watertree_leaves.json


{
  "parent": "block/leaves",
  "textures": {
    "all": "liveinwater:block/watertree_leaves"
  }
}

models\block\watertree_log.json


{
  "parent": "block/cube_column",
  "textures": {
    "end": "liveinwater:block/watertree_log_top",
    "side": "liveinwater:block/watertree_log"
  }
}

Spécifiez block / cube_column pour parent, et appliquez une texture qui fait la distinction entre le haut et le bas et les côtés dans une forme cubique. Spécifions le chemin vers chaque fichier de texture.

models\block\watertree_sapling.json


{
  "parent": "block/cross",
  "textures": {
    "cross": "liveinwater:block/watertree_sapling"
  }
}

models\item\watertree_leaves.json


{
  "parent": "liveinwater:block/watertree_leaves"
}

models\item\watertree_log.json


{
  "parent": "liveinwater:block/watertree_log"
}

models\item\watertree_sapling.json


{
  "parent": "item/generated",
  "textures": {
    "layer0": "liveinwater:item/watertree_sapling"
  }
}

\loot_table\blocks\watertree_leaves.json


{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:item",
              "conditions": [
                {
                  "condition": "minecraft:alternative",
                  "terms": [
                    {
                      "condition": "minecraft:match_tool",
                      "predicate": {
                        "item": "minecraft:shears"
                      }
                    },
                    {
                      "condition": "minecraft:match_tool",
                      "predicate": {
                        "enchantments": [
                          {
                            "enchantment": "minecraft:silk_touch",
                            "levels": {
                              "min": 1
                            }
                          }
                        ]
                      }
                    }
                  ]
                }
              ],
              "name": "liveinwater:watertree_leaves"
            },
            {
              "type": "minecraft:item",
              "conditions": [
                {
                  "condition": "minecraft:survives_explosion"
                },
                {
                  "condition": "minecraft:table_bonus",
                  "enchantment": "minecraft:fortune",
                  "chances": [
                    0.05,
                    0.0625,
                    0.083333336,
                    0.1
                  ]
                }
              ],
              "name": "liveinwater:watertree_sapling"
            }
          ]
        }
      ]
    }
  ]
}

Pour plus de détails, voir [Page de référence](https://minecraft-ja.gamepedia.com/%E3%83%AB%E3%83%BC%E3%83%88%E3%83%86%E3%83%BC% E3% 83% 96% E3% 83% AB).

\loot_table\blocks\watertree_log.json


{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "liveinwater:watertree_log"
        }
      ]
    }
  ]
}

\loot_table\blocks\watertree_sapling.json


{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "liveinwater:watertree_sapling"
        }
      ]
    }
  ]
}

Ajouter au tag

Ajoutez le bloc de journal ajouté à la balise minecraft: logs. Ceci est utilisé pour déterminer la disparition des blocs feuilles (bien qu'il puisse être utilisé dans d'autres parties également), donc si cela n'est pas fait, les blocs feuilles générés commenceront à disparaître immédiatement.

\src\main\resources
   ├ assets
   └ data
      ├ liveinwater
      └ minecraft
         └ tags
            └ blocks
               └ logs.json

** Créez un dossier ** \ src \ main \ resources \ data \ minecraft \ tags \ blocks dans votre dossier de projet et placez-y logs.json. Assurez-vous que ce nom est le même.

logs.json


{
  "replace": false,
  "values": [
    "liveinwater:watertree_log"
  ]
}

En donnant «false» à «remplacer», la description dans ce fichier sera intégrée dans «minecraft: logs» du même nom. Spécifions le bloc dans values.


De même, ajoutez des blocs de feuilles à la balise minecraft: feuilles Ceci est nécessaire pour que le bloc de feuilles ne soit pas jugé comme un obstacle lorsque l'arbre se développe à partir du semis (s'il n'est pas dans l'étiquette de feuilles, il ne sera pas écrasé lors de la création de l'arbre).

\src\main\resources
   ├ assets
   └ data
      ├ liveinwater
      └ minecraft
         └ tags
            └ blocks
               ├ leaves.json
               └ logs.json

leaves.json


{
  "replace": false,
  "values": [
    "liveinwater:watertree_leaves"
  ]
}

2020-09-16_22.37.13.png Lorsque vous appuyez sur F3 dans le jeu pour afficher l'affichage de débogage et placer le curseur sur le bloc, vérifiez que la balise (par exemple, #mineraft: logs) est affichée au centre à droite de l'écran.

Ajout de la classe TreeFeature et de la classe Tree

Celles-ci sont difficiles à expliquer avec des mots, mais les deux sont des classes qui gèrent les arbres. La classe Tree est une classe qui gère l'arbre lui-même et est requise en relation avec les plants qui seront ajoutés plus tard. D'autre part, la classe TreeFeature gère les choses liées à la génération d'arbres, et vous pouvez également obtenir la TreeFeature correspondante de la classe Tree.

\src\main\java\jp\koteko\liveinwater\
   ├ block
   │   └ trees
   │      └ WaterTree.java
   ├ item
   ├ world
   │   └ gen
   │      └ feature
   │         └ WaterTreeFeature.java
   └ LiveInWater.java

WaterTree.java


package jp.koteko.liveinwater.block.trees;

import jp.koteko.liveinwater.world.gen.TreeGenerator;
import net.minecraft.block.trees.Tree;
import net.minecraft.world.gen.feature.BaseTreeFeatureConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;

import javax.annotation.Nullable;
import java.util.Random;

public class WaterTree extends Tree {
    @Nullable
    protected ConfiguredFeature<BaseTreeFeatureConfig, ?> getTreeFeature(Random randomIn, boolean p_225546_2_) {
        return TreeGenerator.WATERTREE.setConfiguration();
    }
}

Étend la classe abstraite Tree pour définir la classe. Définissons la méthode abstraite getTreeFeature pour renvoyer une instance de la classe BaseTreeFeatureConfig avec la configuration donnée au WaterTreeFeature décrit ci-dessous (TreeGenerator sera décrit dans une section ultérieure). Il est conçu pour recevoir des nombres aléatoires, mais cela est utilisé lorsque l'arbre devient une espèce énorme avec une probabilité, changez donc la valeur renvoyée en fonction du nombre aléatoire si nécessaire.


WaterTreeFeature.java


package jp.koteko.liveinwater.world.gen.feature;

import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Codec;
import jp.koteko.liveinwater.block.Blocks;
import net.minecraft.world.gen.blockstateprovider.SimpleBlockStateProvider;
import net.minecraft.world.gen.feature.*;
import net.minecraft.world.gen.foliageplacer.BlobFoliagePlacer;
import net.minecraft.world.gen.placement.AtSurfaceWithExtraConfig;
import net.minecraft.world.gen.placement.Placement;
import net.minecraft.world.gen.treedecorator.BeehiveTreeDecorator;
import net.minecraft.world.gen.trunkplacer.StraightTrunkPlacer;

public class WaterTreeFeature extends TreeFeature {
    public WaterTreeFeature(Codec<BaseTreeFeatureConfig> codec) {
        super(codec);
    }

    public ConfiguredFeature<?, ?> configure() {
        return this.setConfiguration().withPlacement(Placement.field_242902_f.configure(new AtSurfaceWithExtraConfig(10, 0.1F, 1)).func_242728_a());
    }

    public ConfiguredFeature<BaseTreeFeatureConfig, ?> setConfiguration() {
        return this.withConfiguration(
                new BaseTreeFeatureConfig.Builder(
                        new SimpleBlockStateProvider(Blocks.WATERTREE_LOG.getDefaultState()),
                        new SimpleBlockStateProvider(Blocks.WATERTREE_LEAVES.getDefaultState()),
                        new BlobFoliagePlacer(FeatureSpread.func_242252_a(2), FeatureSpread.func_242252_a(0), 3),
                        new StraightTrunkPlacer(5, 2, 0),
                        new TwoLayerFeature(1, 0, 1)
                ).func_236700_a_().func_236703_a_(ImmutableList.of(new BeehiveTreeDecorator(0.002F))).build());
    }
}

Définissez la classe en étendant la classe TreeFeature. Deux méthodes sont définies pour gérer les restrictions imposées par les génériques (<BaseTreeFeatureConfig,?> Part) lors de l'utilisation de Features d'autres classes.

Tout d'abord, le setConfiguration () ci-dessous définit la forme que cet arbre aura (withConfiguration ()). Un constructeur est préparé dans la configuration, et les arguments sont, dans l'ordre, le fournisseur du bloc qui devient le tronc, le fournisseur du bloc qui devient la feuille, la forme d'arrangement des feuilles, la forme d'arrangement du tronc, (argument d'utilisation inconnue ʻAbstractFeatureSizeType). Le nom est difficile à comprendre, mais func_236700_a_ () donne une fonction qui rend ʻignore_vines vraie, etfunc_236703_a_ ()donne un argument (dans cet exemple, celui qui crée une ruche avec une probabilité de 0,002) comme décorateur. Chacun est défini dans le générateur en tant que fonction. Enfin, appelez build () pour créer un BaseTreeFeatureConfig et passez-le à l'argument de withConfiguration ().

Ensuite, configure () donne à la fonctionnalité qui étaitsetConfiguration ()plus de paramètres de l'emplacement du placement (withPlacement ()). On sait qu'il existe de nombreux types de "placement", et il est également possible d'utiliser plusieurs types dans les couches. Par conséquent, il sera nécessaire d'examiner en profondeur le contenu de "Placement" pour créer l'arrangement souhaité. Cette fois, j'ai vérifié et montré un seul exemple. Par exemple, Placement.field_242902_f détermine le nombre de loteries,func_242728_a ()applique enfinSquarePlacement et la méthode getPosisions renvoie une liste de coordonnées aléatoires dans le bloc. Semble faire. Si je comprends un peu plus ce domaine, je peux le résumer dans un autre article.

Génération d'arbres

Enfin, faisons en sorte que l'arbre implémenté soit généré automatiquement lorsque le monde est généré.

\src\main\java\jp\koteko\liveinwater\
   ├ block
   ├ item
   ├ world
   │   └ gen
   │      ├ feture
   │      └ TreeGenerator.java
   └ LiveInWater.java

WorldGenOres.java


package jp.koteko.liveinwater.world.gen;

import com.google.common.collect.Lists;
import jp.koteko.liveinwater.world.gen.feature.WaterTreeFeature;
import net.minecraft.util.RegistryKey;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.WorldGenRegistries;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeGenerationSettings;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.feature.BaseTreeFeatureConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

public class TreeGenerator {
    public static WaterTreeFeature WATERTREE;
    public static ConfiguredFeature<?, ?> CONFIGURED_WATERTREE;

    public static void init() {
        WATERTREE = Registry.register(Registry.FEATURE, "liveinwater:watertree", new WaterTreeFeature(BaseTreeFeatureConfig.field_236676_a_));
        CONFIGURED_WATERTREE = Registry.register(WorldGenRegistries.field_243653_e, "liveinwater:watertree", WATERTREE.configure());
    }

    public static void setup() {
        addTreeToOverworld(CONFIGURED_WATERTREE);
    }

    private static void addTreeToOverworld(ConfiguredFeature<?, ?> featureIn){
        for(Map.Entry<RegistryKey<Biome>, Biome> biome : WorldGenRegistries.field_243657_i.func_239659_c_()) {
            if(!biome.getValue().getCategory().equals(Biome.Category.NETHER) && !biome.getValue().getCategory().equals(Biome.Category.THEEND)) {
                addFeatureToBiome(biome.getValue(), GenerationStage.Decoration.VEGETAL_DECORATION, featureIn);
            }
        }
    }

    public static void addFeatureToBiome(Biome biome, GenerationStage.Decoration decoration, ConfiguredFeature<?, ?> configuredFeature) {
        List<List<Supplier<ConfiguredFeature<?, ?>>>> biomeFeatures = new ArrayList<>(biome.func_242440_e().func_242498_c());
        while (biomeFeatures.size() <= decoration.ordinal()) {
            biomeFeatures.add(Lists.newArrayList());
        }
        List<Supplier<ConfiguredFeature<?, ?>>> features = new ArrayList<>(biomeFeatures.get(decoration.ordinal()));
        features.add(() -> configuredFeature);
        biomeFeatures.set(decoration.ordinal(), features);

        ObfuscationReflectionHelper.setPrivateValue(BiomeGenerationSettings.class, biome.func_242440_e(), biomeFeatures, "field_242484_f");
    }
}

Il est difficile de tout comprendre, alors décidez quoi changer si nécessaire (parce que je l'ai fait). Dans la version 1.16.1, [de la même manière que précédemment](https://qiita.com/koteko/items/aebfc47cf73d7e49baa6#%E6%9C%A8%E3%81%AE%E7%94%9F%E6%88 Il n'a pas été possible d'enregistrer la fonctionnalité dans Biome à% 90). Par conséquent, recherchez un code de référence et reportez-vous au code de BluePower. J'étais autorisé à le faire.

En définissant ʻaddFeatureToBiomeen bas, il est possible d'enregistrer une caractéristique dans Biome de la même manière qu'auparavant. En bref, il semble que la variable membrefield_242484_f de la classe BiomeGenerationSettings` a une liste de fonctionnalités, il semble donc que nous faisons le travail d'écrasement et d'ajout.

Une fois que addFeatureToBiome est défini, il peut être implémenté d'une manière similaire à la méthode précédente. Définition de la méthode ʻaddTreeToOverworld qui s'enregistre auprès d'Overworld's Biome et l'appelle dans la méthode setup. De plus, chaque fonctionnalité doit être déclarée à l'avance et enregistrée avec la méthode ʻinit`. Pour le moment, il semble que cela ne fonctionnera que si vous enregistrez la fonctionnalité et la fonctionnalité configurée comme décrit ci-dessus (même si c'était assez compact, je ne pouvais pas le comprendre complètement).


Enfin, appelez le TreeGenerator.init () TreeGenerator.setup () juste défini dans le fichier principal.

LiveInWater.java


package jp.koteko.liveinwater;

import jp.koteko.liveinwater.world.gen.TreeGenerator;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@Mod(LiveInWater.MOD_ID)
public class LiveInWater
{
    public static final String MOD_ID = "liveinwater";
    private static final Logger LOGGER = LogManager.getLogger();

    public LiveInWater() {
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC);
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC);
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff);

        TreeGenerator.init();

        MinecraftForge.EVENT_BUS.register(this);
    }

    private void setup(final FMLCommonSetupEvent event)
    {
        LOGGER.info("SETUP START");
        TreeGenerator.setup();
        LOGGER.info("SETUP END");
    }

    private void doClientStuff(final FMLClientSetupEvent event) {
        // do something that can only be done on the client
    }

    private void enqueueIMC(final InterModEnqueueEvent event)
    {
        // some example code to dispatch IMC to another mod
    }

    private void processIMC(final InterModProcessEvent event)
    {
        // some example code to receive and process InterModComms from other mods
    }

    @SubscribeEvent
    public void onServerStarting(FMLServerStartingEvent event) {
        LOGGER.info("server starting");
    }
}

Démarrez le jeu et créez un nouveau monde.

2020-09-17_13.09.03.png Un arbre est en cours de génération (comme décrit jusqu'à présent)

2020-09-17_13.11.40.png Une arborescence est en cours de génération (lorsque le placement et la configuration sont modifiés)

référence

[Java] Créons un Minecraft Mod 1.14.4 [9. Ajouter et générer des arbres] --Qiita BluePower/BPWorldGen.java at master · Qmunity/BluePower · GitHub 1.14.3 Tags help - Modder Support - Forge Forums [Biome-Minecraft Wiki](https://minecraft-ja.gamepedia.com/%E3%83%90%E3%82%A4%E3%82%AA%E3%83%BC%E3%83%A0# .E3.83.90.E3.82.A4.E3.82.AA.E3.83.BC.E3.83.A0.E3.82.AB.E3.83.A9.E3.83.BC.E3.81 .AE.E6.B1.BA.E5.AE.9A) [Route Table - Minecraft Wiki](https://minecraft-ja.gamepedia.com/%E3%83%AB%E3%83%BC%E3%83%88%E3%83%86%E3%83%BC % E3% 83% 96% E3% 83% AB) [SOLVED] [1.15.2] A texture issue with cross models? - Modder Support - Forge Forums

Dossier d'implémentation dans Forge 1.16.1 32.0.108

Pour référence, je vais enregistrer un exemple de son implémentation à un niveau qui fonctionne pour le moment avant la mise à niveau de la version Forge.

<détails>

Pliage </ summary>
C'est un groupe de codes qui décrit la génération supplémentaire d'arbres à un niveau temporaire (les semis et les blocs qui composent l'arbre ne sont pas ajoutés).

\src\main\java\jp\koteko\liveinwater\
   ├ block
   ├ item
   ├ world
   │   └ gen
   │      ├ feature
   │      │  └ WaterTreeFeature.java
   │      └ TreeGenerator.java
   └ LiveInWater.java

WaterTreeFeature.java


package jp.koteko.liveinwater.world.gen.feature;

import com.mojang.serialization.Codec;
import net.minecraft.world.gen.feature.BaseTreeFeatureConfig;
import net.minecraft.world.gen.feature.TreeFeature;

public class WaterTreeFeature extends TreeFeature {
    public WaterTreeFeature(Codec<BaseTreeFeatureConfig> codec) {
        super(codec);
    }
}

Cela n'a pas de sens à ce stade, car ce n'est pas encore différent de la classe parente. Contrairement à environ 1.14, il semble qu'une interface appelée «Codec» ait été introduite. D'une manière ou d'une autre, quand je le regarde, il semble que ce soit pour la manipulation générale d'objets de différentes classes.

TreeGenerator.java


package jp.koteko.liveinwater.world.gen;

import com.google.common.collect.ImmutableList;
import jp.koteko.liveinwater.world.gen.feature.WaterTreeFeature;
import net.minecraft.block.Blocks;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.blockstateprovider.SimpleBlockStateProvider;
import net.minecraft.world.gen.feature.BaseTreeFeatureConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.TwoLayerFeature;
import net.minecraft.world.gen.foliageplacer.BlobFoliagePlacer;
import net.minecraft.world.gen.placement.AtSurfaceWithExtraConfig;
import net.minecraft.world.gen.placement.Placement;
import net.minecraft.world.gen.treedecorator.BeehiveTreeDecorator;
import net.minecraft.world.gen.trunkplacer.StraightTrunkPlacer;
import net.minecraftforge.registries.ForgeRegistries;

import java.util.OptionalInt;

public class TreeGenerator {
    public static void setup() {
        addTreeToOverworld(
                new WaterTreeFeature(BaseTreeFeatureConfig.field_236676_a_)
                        .withConfiguration(
                                (new BaseTreeFeatureConfig.Builder(
                                        new SimpleBlockStateProvider(Blocks.ACACIA_WOOD.getDefaultState()),
                                        new SimpleBlockStateProvider(Blocks.BLUE_WOOL.getDefaultState()),
                                        new BlobFoliagePlacer(2, 0, 0, 0, 3),
                                        new StraightTrunkPlacer(5, 2, 0),
                                        new TwoLayerFeature(0, 0, 0, OptionalInt.of(4)))
                                ).func_236700_a_().func_236703_a_(ImmutableList.of(new BeehiveTreeDecorator(0.002F))).build())
                        .withPlacement(Placement.COUNT_EXTRA_HEIGHTMAP.configure(new AtSurfaceWithExtraConfig(10, 0.1F, 1)))
        );
    }

    private static void addTreeToOverworld(ConfiguredFeature<?, ?> featureIn) {
        for(Biome biome : ForgeRegistries.BIOMES) {
            if (!biome.getCategory().equals(Biome.Category.NETHER) && !biome.getCategory().equals(Biome.Category.THEEND)) {
                biome.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, featureIn);
            }
        }
    }
}

C'est fondamentalement le même que dans 1.14, et il est généré en ajoutant la fonctionnalité de l'arbre au biome que vous voulez générer par Biome # addFeature. Beaucoup de noms étaient difficiles à comprendre, et la gestion de «Feature» et «ConfiguredFeature» semblait changer, et «Biome # createDecoratedFeature» manquait également. Le code ci-dessus a été écrit en observant le code vanilla. Pour ConfiguredFeature (new WaterTreeFeature ()), config (dans ce cas, le bloc ou la forme de l'arbre) et le placement (loterie au moment de la génération naturelle) avec withConfiguration () ʻet withPlacement ()Emplacement) est défini. Un constructeur a été préparé pour la configuration, alors utilisez ceci. Dans l'ordre, le bloc de tronc (fournisseur), le bloc de feuille (fournisseur), la forme de la disposition des feuilles, la forme de la disposition du tronc et le type de taille minimale (détails inconnus). Les fournisseurs doivent passer une instance de la classeSimpleBlockStateProvidersauf s'ils font quelque chose de spécial. Modifiez uniquement le type de bloc selon vos besoins. En ce qui concerne la forme de disposition des feuilles et du tronc, il existe plusieurs types utilisés dans la vanille, utilisez donc celui qui convient. Observez les sous-classes deFoliagePlacer, ʻAbstractTrunkPlacer. Spécifiez la hauteur, etc. avec l'argument. Le 5ème argument du constructeur semble être un objet de la classe ʻAbstractFeatureSizeType géré par le nom taille_minimale, mais je ne savais pas comment cela fonctionnerait, donc je vais le faire correspondre avec un autre code. Renvoie une instance de la configuration en appelant build ()au générateur.func_236700_a_ ()spécifie qu'aucune tsuta n'est générée, etfunc_236703_a_ ()spécifie qu'une ruche est générée en passant un argument comme celui-ci. Choisissez le type de placement approprié (voir la classePlacement) et définissez-le avec configure ()`.

Article suivant

Recommended Posts

[Java] Créons un Minecraft Mod 1.16.1 [Ajouter et générer des arbres]
[Java] Créons un Minecraft Mod 1.14.4 [9. Ajouter et générer des arbres]
[Java] Créons un Minecraft Mod 1.14.4 [8. Ajouter et générer du minerai]
[Java] Créons un Minecraft Mod 1.14.4 [4. Ajouter des outils]
[Java] Créons un Minecraft Mod 1.14.4 [5. Ajouter une armure]
[Java] Créons un Minecraft Mod 1.14.4 [7. Add progress]
[Java] Créons un Minecraft Mod 1.16.1 [Ajouter un élément]
[Java] Créons un Minecraft Mod 1.14.4 [1. Ajouter un élément]
[Java] Créons un Minecraft Mod 1.14.4 [2. Ajouter un bloc]
[Java] Créons un Minecraft Mod 1.16.1 [Ajouter un bloc]
[Java] Créons un Minecraft Mod 1.14.4 [3. Ajouter un onglet de création]
[Java] Créons un Minecraft Mod 1.14.4 [Introduction]
[Java] Créons un Minecraft Mod 1.16.1 [Introduction]
[Java] Créons un Minecraft Mod 1.14.4 [99. Mod output]
[Java] Créons un Minecraft Mod 1.14.4 [0. Fichier de base]
[Java] Créons un Minecraft Mod 1.14.4 [édition supplémentaire]
[Java] Créons un Minecraft Mod 1.16.1 [Fichier de base]
[Java] Créer et appliquer un masque des diapositives
Créons un environnement de développement Java (mise à jour)
Installons Docker sur Windows 10 et créons un environnement de vérification pour CentOS 8!
Créons un processus chronométré avec la minuterie de Java! !!
Créons un framework Web ultra-simple avec Java
[Bases de Java] Créons un triangle avec une instruction for
Créez une application JAVA WEB et essayez OMC APM
Créons un système de téléchargement de fichiers à l'aide de l'API Azure Computer Vision et du SDK Java d'Azure Storage
Comment créer une image de conteneur légère pour les applications Java
[Java twig] Créer un combinateur d'analyseur pour l'analyse syntaxique de descente récursive
Création d'un MOB à l'aide du plug-in Minecraft Java Mythicmobs | Préparation 1
Créer un environnement de développement d'équipe Java et JavaScript (construction d'environnement gradle)
Comment créer et lancer un Dockerfile pour Payara Micro
[Java] Créer un fichier temporaire
Créer un tableau et ajouter des colonnes
Instructions Java while et for
Créons une application TODO en Java 4 Implémentation de la fonction de publication
Créons une application TODO en Java 6 Implémentation de la fonction de recherche
Créer une JVM pour la distribution d'applications avec les modules JDK 9 et jlink
Créez une énumération haute performance avec des champs et des méthodes comme Java avec JavaScript
Créons une application TODO en Java 8 Implémentation des fonctions d'édition
Créons une application TODO avec Java 1 Brève explication de MVC
Créons une application TODO en Java 5 Changer l'affichage de TODO
Créez une image Docker pour redoc-cli et enregistrez-la sur Docker Hub
Créons un mécanisme polymorphe de paramètres avec Generic Dao et Hibernate
SDK AWS pour Java 1.11.x et 2.x
Java pour les débutants, les expressions et les opérateurs 1
Comment signer Minecraft MOD
Java pour les débutants, les expressions et les opérateurs 2
Créer un projet Java à l'aide d'Eclipse
Classes et instances Java pour les débutants
Créer un serveur fluentd pour les tests
[Java] Créez un fichier jar compressé et non compressé avec la commande jar
[Java twig] Créer un combinateur d'analyseur pour une analyse de syntaxe descendante récursive (également prendre des notes)
[Docker] Comment créer un environnement virtuel pour les applications Rails et Nuxt.js
[Rails] Comment créer une table, ajouter une colonne et changer le type de colonne
Allons-y avec Watson Assistant (anciennement Conversation) ⑤ Créez un chatbot avec Watson + Java + Slack
Créer un environnement de développement d'applications Web Java avec Docker pour Mac Part2
Créons une application TODO en Java 9 Créer un affichage TODO Trier par date et heure + Définir la date d'échéance sur la date actuelle
Faisons une application TODO avec Java 2 Je veux créer un modèle avec Spring Initializr et créer Hello world