[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Bäume hinzufügen und generieren]

(Dieser Artikel gehört zu einer Reihe von Kommentaren)

Erster Artikel: Einführung Vorheriger Artikel: Block hinzufügen Nächster Artikel:

Vorsichtsmaßnahmen

Bis zu diesem Punkt haben wir den Bestand an fortlaufenden Artikeln übernommen und davon ausgegangen, dass die nicht anders genannten Punkte dieselben sind wie zuvor. Seien Sie jedoch besonders vorsichtig, da wir die Umgebung ** aus diesem Artikel heraus geändert haben.

Umgebung

** Die Version von Minecraft Forge wurde aktualisiert. ** Dies liegt daran, dass es sich um eine in Entwicklung befindliche Version handelt und es viele unentwickelte Teile gibt. Beachten Sie außerdem, dass sich die Version nach dem Update noch in der Entwicklung befindet und täglich aktualisierte Versionen veröffentlicht werden.

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)

Fügen Sie jedes Blockelement hinzu

Fügen Sie Protokolle, Blätter und Sämlingsblöcke hinzu, indem Sie auf Block hinzufügen verweisen.

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

Protokolle werden in der Klasse "Rotated Pillar Block" erstellt, Blätter in der Klasse "Leaves Block" und Sämlinge in der Klasse "Sapling Block". Detaillierte Einstellungen sind für "Block" üblich (z. B. Festlegen von Härte und Widerstand mit ".hardnessAndResistance ()"). Ändern Sie sie daher entsprechend. Jeder der oben genannten Werte ist (sollte) ein Standardwert. Das erste Argument, das an den Konstruktor "SaplingBlock" übergeben wird, ist eine Instanz des vom Sämling generierten Baums. Ich habe es noch nicht definiert, aber ich werde es später erklären. Zusätzlich wurde dem Blockregistrierungsteil eine Beschreibung hinzugefügt. Dadurch wird der Rendertyp festgelegt, um die Textur des Sämlingsblocks korrekt anzuzeigen. Andernfalls wird das Teil, das transparent sein soll, schwarz lackiert. Referenz Schließlich wird die Farbe des Blattblocks so eingestellt, dass sie sich entsprechend der Biomfarbe ändert. Ich habe die Beschreibung von um 1.14.4 so wie sie ist gebracht, also habe ich nicht tief hineingeschaut. Sie können mehr sehen, indem Sie die Klasse "BlockColors" beobachten. Informationen zur Biomfarbe [Referenzseite](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). Wenn dies nicht eingestellt ist, wird die Texturfarbe wie für alle Biome verwendet und kann weggelassen werden.

2020-09-16_22.33.19.png Die Farbe der Blätter ändert sich je nach Biom (da es nach der Implementierung bis zur natürlichen Erzeugung am Ende des Artikels noch keinen Baum auf der Welt gibt)


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

Deklarieren und registrieren Sie BlockItem. Siehe auch Element hinzufügen (https://qiita.com/koteko/items/578c3cfdfd7ef71df9c1).


Stellen Sie "Ressourcen" ein.

\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 }
  }
}

Drehen Sie das Modell je nach Einbaurichtung.

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": "Protokoll des Wasserbaums",
  "item.liveinwater.watertree_leaves": "Wasserbaumblätter",
  "item.liveinwater.watertree_sapling": "Wasserbaumsetzlinge",
  "block.liveinwater.watertree_log": "Protokoll des Wasserbaums",
  "block.liveinwater.watertree_leaves": "Wasserbaumblätter",
  "block.liveinwater.watertree_sapling": "Wasserbaumsetzlinge"
}

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"
  }
}

Geben Sie "block / cube_column" für "parent" an und wenden Sie eine Textur an, die zwischen Ober- und Unterseite und Seiten in kubischer Form unterscheidet. Geben Sie den Pfad zu jeder Texturdatei an.

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"
            }
          ]
        }
      ]
    }
  ]
}

Weitere Informationen finden Sie unter [Referenzseite](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"
        }
      ]
    }
  ]
}

Zum Tag hinzufügen

Fügen Sie den hinzugefügten Protokollblock zum Tag "minecraft: logs" hinzu. Dies wird verwendet, um das Verschwinden von Blattblöcken zu bestimmen (obwohl es auch in anderen Teilen verwendet werden kann). Wenn dies nicht erfolgt, verschwinden die generierten Blattblöcke sofort.

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

** Erstellen Sie einen ** \ src \ main \ resources \ data \ minecraft \ tags \ blocks-Ordner in Ihrem Projektordner und platzieren Sie logs.json darin. Stellen Sie sicher, dass dieser Name identisch ist.

logs.json


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

Wenn Sie "false" für "replace" angeben, wird die Beschreibung in dieser Datei in "minecraft: logs" mit demselben Namen integriert. Geben wir den Block in values an.


Fügen Sie in ähnlicher Weise Blattblöcke zum Tag "Minecraft: Blätter" hinzu. Dies ist erforderlich, damit der Blattblock nicht als Hindernis beurteilt wird, wenn der Baum aus dem Sämling wächst (wenn er nicht im Blatt-Tag enthalten ist, wird er beim Erstellen des Baums nicht überschrieben).

\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 Wenn Sie im Spiel F3 drücken, um die Debug-Anzeige anzuzeigen und den Cursor auf den Block zu setzen, überprüfen Sie, ob das Tag (z. B. "#mineraft: logs") in der Mitte rechts auf dem Bildschirm angezeigt wird.

Hinzufügen der TreeFeature-Klasse und der Tree-Klasse

Diese sind schwer in Worten zu erklären, aber beide sind Klassen, die Bäume verwalten. Die Tree-Klasse ist eine Klasse, die den Baum selbst verwaltet und in Verbindung mit den Sämlingen benötigt wird, die später hinzugefügt werden. Auf der anderen Seite verwaltet die "TreeFeature" -Klasse Dinge im Zusammenhang mit der Baumgenerierung, und Sie können das entsprechende "TreeFeature" auch aus der "Tree" -Klasse abrufen.

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

Erweitert die abstrakte Klasse "Tree", um die Klasse zu definieren. Definieren wir die abstrakte Methode "getTreeFeature", um eine Instanz der "BaseTreeFeatureConfig" -Klasse mit der Konfiguration zurückzugeben, die der unten beschriebenen "WaterTreeFeature" zugewiesen wurde ("TreeGenerator" wird in einem späteren Abschnitt beschrieben). Es ist so konzipiert, dass es Zufallszahlen empfängt. Dies wird jedoch verwendet, wenn der Baum mit einer Wahrscheinlichkeit zu einer riesigen Art heranwächst. Ändern Sie daher den zurückgegebenen Wert gegebenenfalls entsprechend der Zufallszahl.


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

Definieren Sie die Klasse, indem Sie die TreeFeature-Klasse erweitern. Es werden zwei Methoden definiert, um die von Generika auferlegten Einschränkungen zu erfüllen (<BaseTreeFeatureConfig,?> Part), wenn Features aus anderen Klassen verwendet werden.

Zunächst legt die unten stehende setConfiguration () fest, welche Form dieser Baum haben wird (withConfiguration ()). In der Konfiguration wird ein Builder vorbereitet, und die Argumente sind in der Reihenfolge der Anbieter des Blocks, der zum Stamm wird, der Anbieter des Blocks, der zum Blatt wird, die Anordnungsform der Blätter, die Anordnungsform des Stamms (Argument unbekannter Verwendung AbstractFeatureSizeType). Der Name ist schwer zu verstehen, aber func_236700_a_ () gibt eine Funktion an, die ignore_vines wahr macht, und func_236703_a_ () gibt ein Argument (in diesem Beispiel eines, das einen Bienenstock mit einer Wahrscheinlichkeit von 0,002 erstellt) als Dekorateur an. Jedes wird im Builder als Funktion definiert. Rufen Sie abschließend "build ()" auf, um eine "BaseTreeFeatureConfig" zu erstellen und diese an das Argument "withConfiguration ()" zu übergeben.

Als nächstes gibt configure () dem Feature, dassetConfiguration ()war, mehr Einstellungen für den Platzierungsort (withPlacement ()). Es ist bekannt, dass es viele Arten von "Platzierung" gibt, und es ist auch möglich, mehrere Arten in Schichten zu verwenden. Daher ist es notwendig, den Inhalt von "Platzierung" genau zu betrachten, um die gewünschte Anordnung zu erstellen. Diesmal habe ich nur ein Beispiel überprüft und gezeigt. Zum Beispiel bestimmt "Placement.field_242902_f" die Anzahl der Ziehungen, "func_242728_a ()" wendet schließlich "SquarePlacement" an und die "getPosisions" -Methode gibt eine Liste zufälliger Koordinaten im Block zurück. Scheint zu tun. Wenn ich diesen Bereich etwas tiefer verstehe, kann ich ihn in einem anderen Artikel zusammenfassen.

Baumgenerierung

Lassen Sie uns abschließend den implementierten Baum automatisch generieren, wenn die Welt generiert wird.

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

Es ist schwer, alles zu verstehen, also entscheide, was du ändern musst, wenn du musst (weil ich es getan habe). In Version 1.16.1 [auf die gleiche Weise wie zuvor](https://qiita.com/koteko/items/aebfc47cf73d7e49baa6#%E6%9C%A8%E3%81%AE%E7%94%9F%E6%88 Es war nicht möglich, das Feature in Biome bei% 90 zu registrieren. Suchen Sie daher nach einem Referenzcode und beziehen Sie sich auf den Code von BluePower. Ich durfte.

Durch Definieren von "addFeatureToBiome" unten ist es möglich, ein Feature in Biome auf die gleiche Weise wie zuvor zu registrieren. Kurz gesagt, es scheint, dass die Mitgliedsvariable field_242484_f der Klasse BiomeGenerationSettings eine Liste von Funktionen enthält, sodass wir anscheinend die Arbeit des Überschreibens und Hinzufügens erledigen.

Sobald addFeatureToBiome definiert ist, kann der Rest auf ähnliche Weise wie bei der vorherigen Methode implementiert werden. Definierte die "addTreeToOverworld" -Methode, die sich bei Overworlds Biome registriert und innerhalb der "setup" -Methode aufruft. Außerdem sollte jedes Feature im Voraus deklariert und mit der init -Methode registriert werden. Derzeit scheint es nicht zu funktionieren, wenn Sie das Feature und das konfigurierte Feature nicht wie oben beschrieben registrieren (obwohl es ziemlich voll war, konnte ich es nicht vollständig verstehen).


Rufen Sie abschließend den gerade definierten "TreeGenerator.init ()" TreeGenerator.setup () "in der Hauptdatei auf.

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

Starte das Spiel und erschaffe eine neue Welt.

2020-09-17_13.09.03.png Ein Baum wird generiert (wie bisher beschrieben)

2020-09-17_13.11.40.png Ein Baum wird generiert (wenn Platzierung und Konfiguration geändert werden)

Referenz

[Java] Erstellen wir einen Minecraft Mod 1.14.4 [9. Bäume hinzufügen und generieren] --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) [Routentabelle - 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

Implementierungsdatensatz in Forge 1.16.1 32.0.108

Als Referenz werde ich ein Beispiel für die Implementierung auf ein Niveau aufzeichnen, das vor dem Upgrade der Forge-Version vorerst funktioniert.

Folding
Es handelt sich um eine Codegruppe, die die zusätzliche Erzeugung von Bäumen auf temporärer Ebene darstellt (Sämlinge und Blöcke, aus denen der Baum besteht, werden nicht hinzugefügt).
\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);
    }
}

Dies ist an dieser Stelle bedeutungslos, da es sich noch nicht von der übergeordneten Klasse unterscheidet. Anders als um 1.14 scheint eine Schnittstelle namens "Codec" eingeführt worden zu sein. Wenn ich es mir anschaue, scheint es irgendwie für den allgemeinen Umgang mit Objekten verschiedener Klassen zu sein.

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

Es ist im Grunde dasselbe wie in 1.14 und wird durch Hinzufügen der Funktion des Baums zu dem Biom generiert, das Sie mit "Biome # addFeature" generieren möchten. Viele der Namen sind schwer zu verstehen, und es scheint, dass sich die Behandlung von "Feature" und "ConfiguredFeature" geändert hat und "Biome # createDecoratedFeature" ebenfalls verschwunden ist. Der obige Code wurde unter Beachtung des Vanille-Codes geschrieben. Für ConfiguredFeature (new WaterTreeFeature ()) konfigurieren Sie (in diesem Fall den Block oder die Form des Baums) und platzieren Sie (Lotterie zum Zeitpunkt der natürlichen Erzeugung) mit withConfiguration () undwithPlacement () Ort) ist eingestellt. Für die Konfiguration wurde ein Builder vorbereitet. Verwenden Sie diesen. In der Reihenfolge der Stammblock (Anbieter), der Blattblock (Anbieter), die Blattanordnungsform, die Stammanordnungsform und der Mindestgrößentyp (Details unbekannt). Anbieter sollten eine Instanz der Klasse "SimpleBlockStateProvider" übergeben, es sei denn, sie tun etwas Besonderes. Ändern Sie nur den Blocktyp entsprechend. Für die Anordnung der Blätter und des Stammes werden einige Arten in Vanille verwendet, verwenden Sie also die entsprechende. Beachten Sie die Unterklassen von "FoliagePlacer", "AbstractTrunkPlacer". Geben Sie die Höhe usw. mit dem Argument an. Das fünfte Argument des Builders scheint ein Objekt der Klasse "AbstractFeatureSizeType" zu sein, die unter dem Namen "minimal_size" verwaltet wird, aber ich war mir nicht sicher, wie es funktionieren würde, also werde ich es mit anderem Code abgleichen. Gibt eine Instanz der Konfiguration zurück, indem build () an den Builder aufgerufen wird. func_236700_a_ () gibt an, dass kein Tsuta generiert wird, und func_236703_a_ () gibt an, dass ein Bienenstock durch Übergeben eines solchen Arguments generiert wird. Wählen Sie die entsprechende Art der Platzierung aus (siehe Klasse "Platzierung") und legen Sie sie mit "configure ()" fest.

Nächster Artikel

Recommended Posts

[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Bäume hinzufügen und generieren]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [9. Bäume hinzufügen und generieren]
[Java] Lass uns einen Minecraft Mod 1.14.4 erstellen [8. Erz hinzufügen und erzeugen]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [4. Tools hinzufügen]
[Java] Lass uns einen Minecraft Mod 1.14.4 erstellen [5. Rüstung hinzufügen]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [7. Fortschritt hinzufügen]
[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Element hinzufügen]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [1. Element hinzufügen]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [2. Fügen Sie einen Block hinzu]
[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Block hinzufügen]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [3. Registerkarte "Creative hinzufügen"]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [Einführung]
[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Einführung]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [99. Mod-Ausgabe]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [0. Basisdatei]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [Extra Edition]
[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Basisdatei]
[Java] Erstellen und Anwenden eines Folienmasters
Lassen Sie uns eine Java-Entwicklungsumgebung erstellen (Aktualisierung)
Lassen Sie uns Docker unter Windows 10 installieren und eine Überprüfungsumgebung für CentOS 8 erstellen!
Lassen Sie uns mit Javas Timer einen zeitgesteuerten Prozess erstellen! !!
Lassen Sie uns mit Java ein supereinfaches Webframework erstellen
[Java-Grundlagen] Lassen Sie uns ein Dreieck mit einer for-Anweisung erstellen
Erstellen Sie eine JAVA WEB App und probieren Sie OMC APM aus
Erstellen wir ein Datei-Upload-System mit der Azure Computer Vision-API und dem Java SDK von Azure Storage
So erstellen Sie ein leichtes Container-Image für Java-Apps
[Java-Zweig] Erstellen Sie einen Parser-Kombinator für die rekursive Abstiegssyntaxanalyse 2
Erstellen eines MOB mit dem Minecraft Java Mythicmobs-Plug-In | Vorbereitung 1
Erstellen Sie eine Java- und JavaScript-Teamentwicklungsumgebung (Gradle-Umgebungskonstruktion)
So erstellen und starten Sie eine Docker-Datei für Payara Micro
[Java] Erstellen Sie eine temporäre Datei
Erstellen Sie eine Tabelle und fügen Sie Spalten hinzu
Java während und für Anweisungen
Lassen Sie uns eine TODO-App in Java 4 erstellen. Implementierung der Buchungsfunktion
Lassen Sie uns eine TODO-App in Java 6 erstellen. Implementierung der Suchfunktion
Erstellen Sie eine JVM für die App-Verteilung mit JDK 9-Modulen und jlink
Erstellen Sie mit JavaScript eine leistungsstarke Aufzählung mit Feldern und Methoden wie Java
Lassen Sie uns eine TODO-App in Java 8 erstellen. Implementierung von Bearbeitungsfunktionen
Erstellen wir eine TODO-Anwendung mit Java 1 Kurze Erläuterung von MVC
Lassen Sie uns eine TODO-App in Java 5 erstellen. Schalten Sie die Anzeige von TODO um
Erstellen Sie ein Docker-Image für redoc-cli und registrieren Sie es auf Docker Hub
Lassen Sie uns mit Generic Dao und Hibernate einen Parameter-Polymorph-Mechanismus erstellen
AWS SDK für Java 1.11.x und 2.x.
Java für Anfänger, Ausdrücke und Operatoren 1
Wie unterschreibe ich Minecraft MOD?
Java für Anfänger, Ausdrücke und Operatoren 2
Erstellen Sie ein Java-Projekt mit Eclipse
Klassen und Instanzen Java für Anfänger
Erstellen Sie einen fließenden Server zum Testen
[Java] Erstellen Sie mit dem Befehl jar eine JAR-Datei, die sowohl komprimiert als auch nicht komprimiert ist
[Java-Zweig] Erstellen Sie einen Parser-Kombinator für die rekursive absteigende Syntaxanalyse (machen Sie sich auch Notizen).
[Docker] So erstellen Sie eine virtuelle Umgebung für Rails- und Nuxt.js-Apps
[Schienen] So erstellen Sie eine Tabelle, fügen eine Spalte hinzu und ändern den Spaltentyp
Los geht's mit Watson Assistant (ehemals Conversation) ⑤ Erstellen Sie einen Chatbot mit Watson + Java + Slack
Erstellen Sie mit Docker für Mac Teil2 eine Entwicklungsumgebung für Java-Webanwendungen
Erstellen wir eine TODO-App in Java 9 Erstellen einer TODO-Anzeige Sortieren nach Datum und Uhrzeit + Setzen Sie das Fälligkeitsdatum auf das aktuelle Datum
Lassen Sie uns eine TODO-Anwendung mit Java 2 erstellen. Ich möchte eine Vorlage mit Spring Initializr erstellen und eine Hello-Welt erstellen