タグの追加 (1.19.4)

概要

ブロック、アイテムにタグを追加します。

動作確認

2024年01月02日

  • Minecraft 1.19.4
  • Forge 45.2.0

解説

GitHub

タグはバニラでデータパック向けに提供されているシステムで、ブロック・アイテムに対しては旧鉱石辞書と似た利用方法が可能です。本記事ではブロック・アイテムへのバニラやMOD固有のタグ実装を紹介しますが、他のタグに関してもこのチュートリアルと同様の方法で実装が可能です。どのようなタグがありそれを如何に利用するかはパッケージnet.minecraft.data.tagsの各クラスを確認の上、適切なプロバイダーを継承して下さい。

ExampleTNT.java

ExampleTNT/src/main/java/com/tntmodders/exampletnt/ExampleTNT.java


package com.tntmodders.exampletnt;

import com.tntmodders.exampletnt.provider.*;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.PackOutput;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;

@Mod(ExampleTNT.MOD_ID)
public class ExampleTNT {

    public static final String MOD_ID = "exampletnt";

    public ExampleTNT() {
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
        modEventBus.addListener(this::registerProviders);
        ExampleTNTBlocks.register(modEventBus);
        ExampleTNTItems.register(modEventBus);
    }

    private void registerProviders(GatherDataEvent event) {
        DataGenerator gen = event.getGenerator();
        PackOutput packOutput = gen.getPackOutput();
        ExistingFileHelper fileHelper = event.getExistingFileHelper();
        gen.addProvider(event.includeClient(), new ExampleTNTItemModelProvider(packOutput, fileHelper));
        gen.addProvider(event.includeClient(), new ExampleTNTBlockStateProvider(packOutput, fileHelper));
        gen.addProvider(event.includeClient(), new ExampleTNTLangProvider.ExampleTNTLangUS(gen.getPackOutput()));
        gen.addProvider(event.includeClient(), new ExampleTNTLangProvider.ExampleTNTLangJP(gen.getPackOutput()));
        gen.addProvider(event.includeServer(), new ExampleTNTRecipeProvider(gen.getPackOutput()));
        gen.addProvider(event.includeServer(), new ExampleTNTAdvancementProvider(packOutput, event.getLookupProvider(), fileHelper));

        ExampleTNTBlockTagsProvider blockTagsProvider = new ExampleTNTBlockTagsProvider(packOutput, event.getLookupProvider(), fileHelper);
        gen.addProvider(event.includeServer(), blockTagsProvider);
        gen.addProvider(event.includeServer(), new ExampleTNTItemTagsProvider(packOutput, event.getLookupProvider(), blockTagsProvider.contentsGetter(), fileHelper));
    }
}

ExampleTNTBlockTagsProvider.java

ExampleTNT/src/main/java/com/tntmodders/exampletnt/provider/ExampleTNTBlockTagsProvider.java


package com.tntmodders.exampletnt.provider;

import com.tntmodders.exampletnt.ExampleTNT;
import com.tntmodders.exampletnt.ExampleTNTBlocks;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.tags.BlockTags;
import net.minecraftforge.common.data.BlockTagsProvider;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.CompletableFuture;

public class ExampleTNTBlockTagsProvider extends BlockTagsProvider {
    public ExampleTNTBlockTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, @Nullable ExistingFileHelper existingFileHelper) {
        super(output, lookupProvider, ExampleTNT.MOD_ID, existingFileHelper);
    }

    @Override
    protected void addTags(HolderLookup.Provider provider) {
        this.tag(BlockTags.MINEABLE_WITH_HOE).add(ExampleTNTBlocks.LARGE_TNT.get());
    }
}

各種TagsProviderを継承したクラスはメソッドaddTags()をimprimentする必要があります。このメソッド内に記述した内容からタグに関するjsonファイルがrunData実行時に自動で生成されます。
まず、TagsProvider.tag()メソッドで任意のタグを指定し生成するファイルを決めます。ここでは、LARGE_TNTの適正ツールをクワにするためBlockTags.MINEABLE_WITH_HOEを指定します。
その後、add()メソッドの引数に該当タグを追加したい要素を渡します。この引数は可変長引数ですので、幾つかの要素を連続で記述することも可能です。

runData実行後にはresources/data/minecraft/tags/[指定したタグのパス]にjsonファイルが生成されます。バニラのタグを利用する場合はnamespaceがminecraftになっています。

ExampleTNTItemTagsProvider.java

ExampleTNT/src/main/java/com/tntmodders/exampletnt/provider/ExampleTNTItemTagsProvider.java


package com.tntmodders.exampletnt.provider;

import com.tntmodders.exampletnt.ExampleTNT;
import com.tntmodders.exampletnt.ExampleTNTItems;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.data.tags.ItemTagsProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.CompletableFuture;

public class ExampleTNTItemTagsProvider extends ItemTagsProvider {
    public static final TagKey<Item> TOSS_EXPLOSIVE = ItemTags.create(new ResourceLocation(ExampleTNT.MOD_ID, "toss_explosive"));

    public ExampleTNTItemTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, CompletableFuture<TagLookup<Block>> future, @Nullable ExistingFileHelper existingFileHelper) {
        super(output, lookupProvider, future, ExampleTNT.MOD_ID, existingFileHelper);
    }

    @Override
    protected void addTags(HolderLookup.Provider provider) {
        this.tag(TOSS_EXPLOSIVE).add(Items.CREEPER_SPAWN_EGG, ExampleTNTItems.SMALL_TNT.get());
    }
}

このクラスでは、アイテムのタグとしてMOD独自のタグを定義しています。このタグはstatic finalな定数を用いて、ItemTags.create()などのメソッドを利用して生成すると使いやすいです。独自のタグもバニラのタグと同様に登録することでjsonファイルが生成されます。

runData実行後にはresources/data/[modid]/tags/[指定したタグのパス]にjsonファイルが生成されます。ItemTags.create()などのメソッドで定義したResourceLocationに生成されることになります。

ExampleTNTHooks.java

ExampleTNT/src/main/java/com/tntmodders/exampletnt/ExampleTNTHooks.java


package com.tntmodders.exampletnt;

import com.tntmodders.exampletnt.provider.ExampleTNTItemTagsProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.world.entity.monster.Phantom;
import net.minecraft.world.level.Level;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.EntityMobGriefingEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.living.MobSpawnEvent;
import net.minecraftforge.event.level.ExplosionEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(modid = ExampleTNT.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class ExampleTNTHooks {
    @SubscribeEvent
    public static void itemTossEvent(ItemTossEvent event) {
        if (event.getEntity().getItem().is(ExampleTNTItems.SMALL_TNT.get()) && event.getPlayer() instanceof ServerPlayer serverPlayer) {
            serverPlayer.getAdvancements().award(serverPlayer.getServer().getAdvancements().getAdvancement(new ResourceLocation(ExampleTNT.MOD_ID, "small_tnt")), "toss_small_tnt");
        }
        if (event.getEntity().getItem().is(ExampleTNTItemTagsProvider.TOSS_EXPLOSIVE) && !event.getEntity().getLevel().isClientSide()) {
            event.getEntity().getLevel().explode(event.getPlayer(), event.getEntity().getX(), event.getEntity().getY(), event.getEntity().getZ(), 1f, true, Level.ExplosionInteraction.TNT);
        }
    }
}

タグはアイテムやブロックなどのis()メソッドでの判定に利用できます。なお、メソッドitemTossEvent()で利用しているように、is()メソッドは同名で引数の違うメソッドも存在しますが、基本的にタグでの判定にも対応しています。詳細は各クラスを確認して下さい。

itemTossEvent()2つ目のif節では、今回新しく実装したアイテムのタグExampleTNTItemTagsProvider.TOSS_EXPLOSIVEを持つアイテムをドロップした際に爆発が起こるように設定しています。runDataを実行し正しくjsonファイルが生成されていれば、クリーパーエッグや小型TNTなどこのタグを付与した任意のアイテムで爆発が起こせるようになっています。

タグは材料の色を問わないレシピや登れるブロックの判定などにも利用されています。実装したいバニラ要素に関して、先にタグが存在するか確認した上で行うと効率的かつ拡張性高く実装ができます。

リンク


前:進捗の追加

次: