Minecraft Mod開発をKotlinとFabricで!ゼロから始める完全ガイド

はい、承知いたしました。Minecraft Mod開発をKotlinとFabricで行うための、約5000語の詳細な完全ガイド記事を記述します。


Minecraft Mod開発をKotlinとFabricで!ゼロから始める完全ガイド

Minecraftの世界に自分だけの要素を追加してみたいと思ったことはありませんか?新しいアイテム、ユニークなブロック、不思議な生物、全く新しいゲームシステム… これらを実現するのがMod開発です。

本記事では、Javaの代わりにKotlinというモダンで扱いやすい言語を使用し、軽量かつ高速なModローダーであるFabricを使って、ゼロからMinecraft Modを開発する方法を、約5000語のボリュームで徹底的に解説します。プログラミング経験がない方や、Minecraft Mod開発が初めての方でも安心して読み進められるよう、環境構築から基本的なアイテム・ブロックの追加、さらに高度な要素まで、具体的な手順とコード例を交えながら丁寧に説明します。

さあ、あなただけのMinecraft世界を創造する旅に出ましょう!

1. はじめに:Mod開発の魅力とKotlin & Fabricの選択

Minecraft Mod開発は、無限の可能性を秘めた創造的な活動です。既存のゲームプレイを拡張するだけでなく、全く新しいゲームに変貌させることすら可能です。あなたが思い描く「こうだったら面白いのに!」を形にすることができます。

Mod開発の主要なプラットフォームとしては、歴史の長いForgeと、比較的新しいFabricがあります。また、開発言語としてはJavaが主流ですが、近年ではKotlinの人気が高まっています。

なぜ本ガイドでは KotlinFabric を推奨するのでしょうか?

  • Kotlin: Java仮想マシン(JVM)上で動作するモダンなプログラミング言語です。Javaとの完全な相互運用性を持ちながら、より簡潔で安全なコードを書くことができます。特にNull安全性の強化や、データクラス、拡張関数といった機能は開発効率を大幅に向上させます。Javaしか知らない方も、これを機にKotlinの魅力を体験してみてください。
  • Fabric: Forgeと比較して、より軽量でセットアップが容易なModローダーです。Minecraftのアップデートへの追従が比較的早く、開発中のバージョンへの対応も迅速です。また、小さなModや特定の機能を目的としたMod開発に適しており、依存関係もシンプルになりやすい傾向があります。Mod開発の学習を始めるにあたって、Fabricは優れた選択肢と言えるでしょう。

本ガイドを最後まで読めば、以下のことができるようになります。

  • Mod開発に必要な環境を構築できる。
  • Fabric Modプロジェクトをセットアップできる。
  • Kotlinの基本的な構文を理解し、Mod開発に応用できる。
  • 新しいアイテムやブロックをゲームに追加できる。
  • レシピを定義し、アイテムやブロックを作成できるようにする。
  • Minecraftのイベントを捉えて、Modの動作を制御できる。
  • 作成したModをゲーム内で実行し、デバッグできる。
  • 完成したModを他の人に配布できる形にビルドできる。

これらの知識を基盤として、さらに複雑でオリジナティブなMod開発に進むことが可能になります。

2. 開発環境の準備

Mod開発を始める前に、必要なツールを準備しましょう。

2.1. 必要なものリスト

  1. JDK (Java Development Kit): Minecraft、Fabric、そしてKotlinコードをコンパイル・実行するために必要です。Java 17以降が推奨されます(Modding対象のMinecraftのバージョンによりますが、近年のバージョンではJava 17が必要です)。
  2. IDE (統合開発環境): コードを記述し、プロジェクトを管理するための強力なツールです。IntelliJ IDEA がKotlin開発に最も適しており、強く推奨します(Community Editionで十分です)。
  3. Git: プロジェクトのバージョン管理に役立ちます。必須ではありませんが、使用することをおすすめします。
  4. インターネット接続: 開発環境のダウンロード、ライブラリの取得に必要です。

2.2. JDKのインストール

Java 17以降のJDKをインストールします。様々な配布元がありますが、Adoptium Temurin(旧AdoptOpenJDK)は無料で利用でき、実績もあり推奨されています。

  1. Adoptium Temurinのウェブサイト(adoptium.net)にアクセスします。
  2. OSとアーキテクチャを選択し、Java 17以降のバージョン(通常はLatest releaseが表示されています)のHotSpot JVMを選びます。
  3. インストーラー (.msi for Windows, .pkg for macOS, .deb/.rpm for Linux) をダウンロードして実行します。
  4. インストールウィザードに従います。環境変数 JAVA_HOME の設定や、PATH へのJava bin ディレクトリの追加オプションがある場合は、有効にしておくことを推奨します。

インストール後、コマンドプロンプトやターミナルを開き、java -version および javac -version を実行して、インストールが成功したか確認します。インストールしたバージョンが表示されれば成功です。

2.3. IntelliJ IDEAのインストールと設定

IntelliJ IDEAはKotlin開発に最適なIDEです。Community Editionは無料で利用できます。

  1. JetBrainsのウェブサイト(jetbrains.com/idea/download)にアクセスします。
  2. OSを選択し、Community Editionをダウンロードします。
  3. インストーラーを実行し、ウィザードに従ってインストールします。デフォルト設定で問題ありません。

インストール後、IntelliJ IDEAを起動します。

  • Kotlinプラグイン: IntelliJ IDEAには通常Kotlinプラグインが標準で含まれていますが、念のため確認します。「File」→「Settings」(macOSでは「IntelliJ IDEA」→「Preferences」)を開き、「Plugins」を選択します。検索バーに「Kotlin」と入力し、プラグインがインストールされ、有効になっていることを確認します。必要であればインストールし、IDEを再起動します。
  • Gradleの設定: Fabric Modding TemplateはGradleというビルドツールを使用します。IntelliJ IDEAはGradleを自動で認識してくれますが、設定を確認しておくと良いでしょう。「File」→「Settings」(Preferences)→「Build, Execution, Deployment」→「Build Tools」→「Gradle」と進み、「Use Gradle wrapper task configuration」が選択されていることを確認します。

2.4. Gitのインストール (任意だが推奨)

Gitはプロジェクトの変更履歴を管理し、以前の状態に戻したり、共同開発を行ったりするのに非常に役立ちます。

  1. Gitの公式ウェブサイト(git-scm.com/downloads)にアクセスします。
  2. OSを選択し、インストーラーをダウンロードします。
  3. インストーラーを実行します。オプションが多くて迷うかもしれませんが、特に理由がなければデフォルト設定で進めても大丈夫です。

インストール後、コマンドプロンプトやターミナルを開き、git --version を実行して確認します。

2.5. Fabric Modding Templateの取得とセットアップ

Mod開発の基盤として、Fabric公式が提供するModding Templateを利用するのが最も効率的です。

  1. Fabric Examplesのリポジトリ(github.com/FabricMC/fabric-example-mod)にアクセスします。
  2. このリポジトリをローカルにクローン(複製)します。Gitがインストールされていれば、コマンドプロンプトやターミナルで以下のコマンドを実行します。
    bash
    git clone https://github.com/FabricMC/fabric-example-mod.git MyKotlinMod
    cd MyKotlinMod

    MyKotlinMod の部分は好きなプロジェクト名に変更してください。
    Gitを使わない場合は、「Code」ボタンをクリックして「Download ZIP」を選択し、ダウンロードしたファイルを解凍しても構いません。ただし、Gitの使用を強く推奨します。

  3. プロジェクトの準備: クローン/解凍したディレクトリをIntelliJ IDEAで開きます。「File」→「Open」を選択し、クローン/解凍した MyKotlinMod ディレクトリを指定します。IntelliJ IDEAがGradleプロジェクトとして認識し、依存関係のダウンロードやプロジェクトの同期を自動で行います。これには時間がかかる場合があります。

  4. Kotlinへの移行: デフォルトのExample ModはJavaで書かれています。これをKotlinベースに変換します。

    • src/main/java/net/fabricmc/example/ExampleMod.java を削除します。
    • src/main/resources/fabric.mod.json を開きます。entrypoints セクションにある main の値を、これから作成するKotlinのエントリポイントクラスに合わせて変更します。例えば、com.yourname.mykotlinmod.MyKotlinMod::onInitialize のように変更します(com.yourname.mykotlinmod は好きなパッケージ名に、MyKotlinMod はクラス名に変更してください)。
    • src/main/java ディレクトリを右クリックし、「Mark Directory as」→「Sources Root」を選択します。
    • src/main ディレクトリ内に新しく kotlin ディレクトリを作成します。
    • src/main/kotlin ディレクトリ内に、fabric.mod.json で指定したパッケージ構造(例: com/yourname/mykotlinmod)に合わせてディレクトリを作成します。
    • そのパッケージ内に、fabric.mod.json で指定したエントリポイントクラス(例: MyKotlinMod.kt)を新しくKotlinファイルとして作成します。
  5. build.gradle の設定: プロジェクトのルートにある build.gradle ファイルを編集し、Kotlinを使用するための設定を追加します。

    • ファイルの冒頭にKotlinプラグインを追加します。
      gradle
      plugins {
      id 'fabric-loom' version '1.6-SNAPSHOT' // Fabric Loomプラグイン (バージョンは異なる場合があります)
      id 'java'
      id 'org.jetbrains.kotlin.jvm' version '1.9.22' // Kotlin JVMプラグイン (バージョンは異なる場合があります)
      }

      fabric-loom および org.jetbrains.kotlin.jvm のバージョンは、最新の安定版やFabric Modding Templateの推奨バージョンに合わせて適宜変更してください。
    • repositories ブロックにMaven Centralリポジトリを追加します。Kotlin関連のライブラリはこちらから取得されます。
      gradle
      repositories {
      // Add repositories for dependencies here
      // when downloading jars itself and not dependent on loom
      mavenCentral() // Kotlinライブラリのために追加
      }
    • dependencies ブロックにKotlin標準ライブラリへの依存関係を追加します。
      “`gradle
      dependencies {
      // To change the versions see the gradle.properties file
      minecraft “com.mojang:minecraft:${project.minecraft_version}”
      mappings “net.fabricmc:yarn:${project.yarn_mappings}:v2”
      modImplementation “net.fabricmc:fabric-loader:${project.loader_version}”

      // Fabric API. This is technically optional, but you probably want it anyway.
      // If you don't want to depend on the API, pass `fabricApi` as the first argument
      // in fabric.mod.json entrypoints.
      modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
      
      // Add your own dependencies here.
      implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.22" // Kotlin標準ライブラリ (バージョンはKotlinプラグインと合わせる)
      

      }
      ``kotlin-stdlib-jdk8のバージョンは、上で設定したorg.jetbrains.kotlin.jvm` プラグインのバージョンと合わせる必要があります。

これで、KotlinでFabric Modを開発するための基本的なプロジェクト設定が完了しました。IntelliJ IDEAのGradleツールウィンドウ(通常右側にあります)で「Reload All Gradle Projects」ボタン(更新マークのアイコン)をクリックし、変更を適用してください。

2.6. プロジェクト構造の解説

セットアップが完了したプロジェクトの主要なディレクトリ構造を理解しておきましょう。

MyKotlinMod/
├── .gradle/ // Gradleのキャッシュなど (気にしなくて良い)
├── .idea/ // IntelliJ IDEAの設定ファイル (気にしなくて良い)
├── build/ // ビルド成果物が出力されるディレクトリ (ビルド時に生成される)
├── gradle/ // Gradle Wrapper関連ファイル
│ └── wrapper/
├── src/
│ ├── main/ // メインのModソースコードとリソース
│ │ ├── kotlin/ // ★ あなたのKotlinソースコードを置く場所
│ │ │ └── com/yourname/mykotlinmod/
│ │ │ └── MyKotlinMod.kt // ★ メインエントリポイント
│ │ └── resources/ // Modのリソースファイル (テクスチャ、モデル、言語ファイル、fabric.mod.jsonなど)
│ │ ├── assets/ // アイテムやブロックのテクスチャ、モデル、言語ファイルなどを置く場所
│ │ │ └── mykotlinmod/ // ★ あなたのMod IDと同じ名前にする
│ │ │ ├── lang/
│ │ │ │ └── en_us.json // ★ 言語ファイル
│ │ │ ├── models/
│ │ │ │ ├── block/
│ │ │ │ └── item/
│ │ │ └── textures/
│ │ │ ├── block/
│ │ │ └── item/
│ │ └── fabric.mod.json // ★ Modの基本情報ファイル
│ └── test/ // テストコードを置く場所 (任意)
├── .gitattributes // Git設定 (あれば)
├── .gitignore // Gitが無視するファイル指定
├── build.gradle // ★ Gradleビルドスクリプト (Modの設定、依存関係、ビルド方法などを記述)
├── gradle.properties // プロジェクト全体で使用するプロパティ (Minecraftバージョンなど)
├── gradlew // Gradle Wrapper実行スクリプト (Linux/macOS)
├── gradlew.bat // Gradle Wrapper実行スクリプト (Windows)
└── settings.gradle // Gradleマルチプロジェクト設定 (通常は編集不要)

特に重要なのは src/main/kotlin (ソースコード)、src/main/resources (リソース)、fabric.mod.json (Mod情報)、build.gradle (ビルド設定)です。assets ディレクトリ内のサブディレクトリ名は、あなたのMod ID(fabric.mod.json で設定)と同じ名前にする必要があります。これはMinecraftがリソースをロードする際のルールです。

3. Fabric Moddingの基本

Fabric Mod開発の中核となる概念と、最もシンプルなModの実装方法を学びます。

3.1. fabric.mod.json の解説

fabric.mod.json は、Modに関する基本的な情報(名前、バージョン、開発者など)や、ModローダーがModをロードするために必要な情報(エントリポイント、依存関係など)を記述するファイルです。

“`json
{
“schemaVersion”: 1,
“id”: “mykotlinmod”, // ★ あなたのModのユニークなID。小文字、英数字、アンダースコアのみ推奨。
“version”: “${version}”, // ★ Modのバージョン。gradle.propertiesから自動取得される。

“name”: “My Kotlin Mod”, // ★ Modの表示名
“description”: “This is an example mod written in Kotlin with Fabric.”, // Modの説明
“authors”: [
“Your Name” // 開発者名
],
“contact”: {
“homepage”: “https://fabricmc.net/”,
“sources”: “https://github.com/FabricMC/fabric-example-mod”
},

“license”: “CC0-1.0”, // ライセンス情報
“icon”: “assets/mykotlinmod/icon.png”, // Modアイコン (任意)

“environment”: ““, // Modが動作する環境 (“” = クライアント&サーバー, “client” = クライアントのみ, “server” = サーバーのみ)
“entrypoints”: {
// ★ Modがロードされたときに最初に実行されるクラスを指定
“main”: [
“com.yourname.mykotlinmod.MyKotlinMod” // ★ パッケージ名.クラス名
],
“client”: [], // クライアント専用のエントリポイント (任意)
“server”: [] // サーバー専用のエントリポイント (任意)
},
“mixins”: [
“mykotlinmod.mixins.json” // Mixinを使用する場合の設定 (高度なトピック)
],

“depends”: {
// ★ 依存するModやMinecraftのバージョンを指定
“fabricloader”: “>=0.15.0”, // Fabric Loaderの最小バージョン
“minecraft”: “~1.20.1”, // 対象のMinecraftバージョン (正確なバージョン範囲を指定)
“java”: “>=17”, // 必要なJavaのバージョン
“fabric-api”: “” // Fabric APIに依存する場合 (バージョンは任意で指定可)
},
“suggests”: {
// 依存はしないが、併用を推奨するModなど
“another-mod”: “

}
}
“`

  • id: Modのユニークな識別子です。他のModと重複しないように、通常は全て小文字のスネークケース(例: my_awesome_mod)で、あなたの名前やニックネームを接頭辞としてつける(例: yourname_awesome_mod)のが良い慣習です。これはゲーム内のリソース名やRegistryキーのネームスペースとしても使用されます。
  • version: Modのバージョンです。${version} としておくと、gradle.properties ファイルの version プロパティから値が自動的に挿入されます。
  • entrypoints: Modの開始点(エントリポイント)を定義します。main はクライアント・サーバー両方で実行される基本的なエントリポイントです。ここに指定したクラスの特定メソッドが、Modロード時に呼び出されます。
  • depends: このModが動作するために必要な他のModやソフトウェア(Fabric Loader, Minecraft, Javaなど)を指定します。Fabric APIを使用する場合はここに追加します。

3.2. Entrypointとは何か?

Entrypointは、Fabric ModローダーがModをロードする際に「まずここを実行してください」と指定するクラスとメソッドのことです。fabric.mod.jsonentrypoints セクションで定義します。

最も一般的なエントリポイントは main で、net.fabricmc.api.ModInitializer インターフェースを実装したクラスを指定します。このインターフェースには onInitialize() というメソッドがあり、Modがロードされる際にFabricによって呼び出されます。ここにModの初期化処理(アイテムやブロックの登録、イベントリスナーの登録など)を記述します。

クライアント専用の処理を行いたい場合は client エントリポイント(net.fabricmc.api.ClientModInitializer)、サーバー専用の場合は server エントリポイント(net.fabricmc.api.DedicatedServerModInitializer)を使用します。これらはそれぞれ onInitializeClient()onInitializeServer() メソッドを持ちます。

3.3. メインクラス(Modエントリポイント)の実装

src/main/kotlin/com/yourname/mykotlinmod/MyKotlinMod.kt に、fabric.mod.json で指定したエントリポイントクラスを作成します。

“`kotlin
package com.yourname.mykotlinmod

import net.fabricmc.api.ModInitializer
import org.slf4j.LoggerFactory // Logbackライブラリ (Fabricに付属)

// objectキーワードでシングルトンオブジェクトとして定義
object MyKotlinMod : ModInitializer {

// ロガーを作成。Mod IDを名前として使用するのが一般的。
// Kotlinのlateinitキーワードで、後に初期化することを宣言。
// または、val logger = LoggerFactory.getLogger("mykotlinmod") としても良い。
private val logger = LoggerFactory.getLogger("mykotlinmod") // fabric.mod.jsonのIDと同じ

override fun onInitialize() {
    // Modの初期化コードはここに記述する
    logger.info("Hello, Fabric world from Kotlin!")

    // TODO: アイテム、ブロック、イベントリスナーなどの登録処理をここに追加していく
}

}
“`

  • Kotlinでは object キーワードを使うことで、そのクラスのインスタンスが一つだけ存在することを保証するシングルトンとしてクラスを定義できます。Modのエントリポイントは通常シングルトンとして扱われるため、object が適しています。
  • net.fabricmc.api.ModInitializer インターフェースを実装し、その唯一のメソッドである onInitialize() をオーバーライド(override キーワードを使用)します。
  • org.slf4j.LoggerFactory を使用してロガーを取得します。これにより、開発中の情報やエラーメッセージをゲームのログファイルに出力できます。getLogger() に渡す名前は、Mod IDを使うのが一般的です。
  • onInitialize() メソッド内に、Modがロードされたときに実行したい初期化処理を記述します。今はシンプルにログを出力するだけですが、後でアイテムやブロックの登録処理などをここに追加していきます。

3.4. 簡単な”Hello, World!” Modの実装(ログ出力)

上記のコードは、既に”Hello, World!”に相当する機能(Modロード時にログを出力する)を持っています。これが最もシンプルなFabric Modの実装です。

3.5. 開発環境での実行方法

IntelliJ IDEAでModをテスト実行するには、Gradleタスクを使用します。

  1. IntelliJ IDEAの右側にあるGradleツールウィンドウを開きます。
  2. あなたのプロジェクト(例: MyKotlinMod)を展開し、「Tasks」→「fabric loom」を展開します。
  3. Modをクライアントで実行する場合: runClient タスクをダブルクリックします。
  4. Modをサーバーで実行する場合: runServer タスクをダブルクリックします。

これにより、Fabric LoaderがインストールされたMinecraftのインスタンスが、あなたのModを読み込んだ状態で起動します。

runClient を実行すると、通常のMinecraftランチャーとは別のウィンドウでMinecraftが起動します。メインメニューの「Mods」ボタン(Fabric Loaderが追加します)をクリックすると、インストールされているModのリストが表示され、あなたのMod (My Kotlin Mod) が含まれていることが確認できます。

ゲームを起動し、IntelliJ IDEAのRunウィンドウ(画面下部)を見ると、Modの初期化時に出力したログメッセージ(”Hello, Fabric world from Kotlin!”)が表示されているはずです。

3.6. ビルド方法と配布可能なJarファイルの作成

Modの開発がある程度進み、他の人に配布したい場合は、ModのJarファイルをビルドする必要があります。

  1. IntelliJ IDEAのGradleツールウィンドウを開きます。
  2. プロジェクトの「Tasks」→「build」を展開します。
  3. build タスクをダブルクリックします。

これにより、Modのコンパイル、リソースのコピー、そして配布可能なJarファイルの作成が行われます。ビルドが成功すると、プロジェクトディレクトリ内の build/libs/ ディレクトリに以下の2つのファイルが出力されます。

  • your-mod-id-version.jar (例: mykotlinmod-1.0.0.jar):これが配布可能なModファイルです。
  • your-mod-id-version-dev.jar (例: mykotlinmod-1.0.0-dev.jar):開発用のファイルで、通常は配布しません。デバッグ情報などが含まれています。

配布可能なJarファイル (-dev.jar がついていない方) を、他の人のMinecraftインストールディレクトリにある mods フォルダに入れることで、そのModを使用できるようになります。

4. Kotlinの基本(Mod開発に必要な範囲)

Mod開発を進める上で必要となる、Kotlinの基本的な文法や概念を学びましょう。KotlinはJavaと多くの共通点がありますが、よりモダンで便利な機能が追加されています。

4.1. 変数 (var, val)、データ型

  • val: 読み取り専用(immutable)の変数を宣言します。一度値を代入したら変更できません。Javaでいう final に近いです。
    kotlin
    val PI: Double = 3.14159 // 型を指定
    val greeting = "Hello" // 型推論される
  • var: 読み書き可能な(mutable)変数を宣言します。値を後から変更できます。Javaでいう通常の変数と同じです。
    kotlin
    var count: Int = 0 // 型を指定
    var message = "Initial message" // 型推論される
    count = 1
    message = "New message"

    Mod開発では、定数や一度設定したら変わらないものには val を、状態が変化するものには var を使い分けるのが良いプラクティスです。

Kotlinは静的型付け言語ですが、多くの場合コンパイラが型を推論してくれるため、明示的な型指定を省略できます。

4.2. 関数 (fun)

関数は fun キーワードで定義します。

“`kotlin
fun add(a: Int, b: Int): Int { // 引数名: 型, 引数名: 型): 戻り値の型
return a + b
}

// 単一式関数 (single-expression function) はreturnと波括弧を省略できる
fun multiply(a: Int, b: Int): Int = a * b

// 戻り値がない場合はUnit (または省略)
fun printMessage(message: String) {
println(message)
}

// Unitは省略可能
fun printMessage2(message: String): Unit {
println(message)
}
“`

4.3. クラスとオブジェクト

クラスは class キーワードで定義します。Kotlinではプライマリコンストラクタがクラスヘッダーに記述できます。

“`kotlin
class MyItem(val settings: net.minecraft.item.Item.Settings) : net.minecraft.item.Item(settings) {
// プロパティやメソッドを定義

fun use() {
    // アイテム使用時のロジック
}

}

// クラスのインスタンス化にnewキーワードは不要
val customItem = MyItem(net.minecraft.item.Item.Settings()) // Item.Settings() はMinecraft APIのクラス
“`

  • プライマリコンストラクタの引数に val または var をつけると、その引数はクラスのプロパティになります。
  • コロン : の後にスーパークラスやインターフェースを指定して継承・実装します。

4.4. Null安全性 (?, !!, Elvis演算子 ?:)

Kotlinの大きな特徴の一つがNull安全性です。デフォルトでは、非Null型には null を代入できません。

  • ?: 型名の後ろに ? をつけると、その変数が null を保持する可能性がある Nullable 型になります。Nullable型の変数にアクセスする際は、Nullチェックを行うか、安全呼び出し演算子 ?. を使用する必要があります。
    “`kotlin
    var nullableString: String? = “Hello”
    nullableString = null // NullableなのでOK

    // 安全呼び出し: nullでなければlengthを取得、nullならnullを返す
    val length = nullableString?.length

    // let 関数と安全呼び出しを組み合わせて、nullでない場合のみ処理を実行
    nullableString?.let {
    // ここはnullableStringがnullでない場合にのみ実行される
    println(“String is not null: $it”)
    }
    * **`!!`**: 非Nullアサーション演算子です。変数がnullでないと断言する場合に使用します。変数がnullだった場合、`NullPointerException` が発生します。これは極力避けるべきですが、Java APIとの連携など、コンパイラがNull安全性を判断できない場合に使用することがあります。kotlin
    val nonNullString: String = nullableString!! // nullableStringがnullだとここでエラー
    * **Elvis演算子 `?:`**: Nullableな変数がnullの場合に、代替となる値を指定できます。kotlin
    val name: String? = null
    val displayName = name ?: “Guest” // nameがnullなら”Guest”が代入される
    “`

Mod開発では、Minecraft APIがJavaで書かれているため、Nullableな型やJavaのNullableアノテーション(@Nullable など)に注意しながらKotlinコードを書く必要があります。

4.5. プロパティ、バックフィールド

Kotlinでは、Javaのフィールドとgetter/setterメソッドをまとめて「プロパティ」として扱います。

“`kotlin
class Example {
var mutableProperty: String = “initial” // setterとgetterが自動生成される
val immutableProperty: Int = 10 // getterのみ自動生成される

// カスタムgetter/setterを定義することも可能
var customProperty: Int = 0
    get() = field * 2 // fieldはバックフィールドを指す
    set(value) {
        if (value >= 0) {
            field = value
        }
    }

}

val obj = Example()
println(obj.immutableProperty) // getterが呼ばれる
obj.mutableProperty = “changed” // setterが呼ばれる
obj.customProperty = 5 // custom setterが呼ばれる (fieldに5が代入される)
println(obj.customProperty) // custom getterが呼ばれる (field * 2 = 10 が返される)
“`

4.6. オブジェクト式、シングルトン (object)

  • シングルトン (object): 前述の MyKotlinMod のように、クラスと同時にその唯一のインスタンスを定義します。グローバルな定数や、状態を持たないユーティリティ関数などをまとめるのに便利です。
    “`kotlin
    object Constants {
    val MY_MOD_ID = “mykotlinmod”
    val MAX_STACK_SIZE = 64
    }

    // どこからでも Constants.MY_MOD_ID のようにアクセスできる
    * **コンパニオンオブジェクト (`companion object`)**: クラスの内部に定義し、そのクラスのインスタンスに関係なくアクセスできるメンバー(Javaのstaticメンバーに相当)を定義します。ファクトリメソッドやクラス定数によく使われます。kotlin
    class ItemHelper {
    companion object {
    // Javaの static final String TAG = “tag”; に相当
    const val TAG = “my_item_tag”

        // Javaの static Item createDefault(); に相当
        fun createDefault(): net.minecraft.item.Item {
            return net.minecraft.item.Item(net.minecraft.item.Item.Settings())
        }
    }
    

    }

    // ItemHelper.TAG や ItemHelper.createDefault() のようにアクセスできる
    * **オブジェクト式 (Object Expression)**: 匿名クラスをその場で作成する場合に使用します。Javaの匿名クラスに相当します。インターフェースの実装などによく使われます。kotlin
    // Javaの new Runnable() { … } に相当
    val runnable = object : Runnable {
    override fun run() {
    println(“Running in a thread”)
    }
    }
    “`

4.7. 拡張関数

既存のクラスに新しいメソッドやプロパティを追加する機能です。元のクラスのソースコードを変更することなく機能を追加できるため、ユーティリティ関数などの定義に便利です。

“`kotlin
// String クラスに isPalindrome という関数を追加
fun String.isPalindrome(): Boolean {
return this == this.reversed()
}

// どこでも String オブジェクトに対して .isPalindrome() を呼び出せる
val str1 = “madam”
val str2 = “hello”
println(str1.isPalindrome()) // true
println(str2.isPalindrome()) // false
“`
Mod開発では、Minecraft APIのクラスに独自の便利なメソッドを追加したい場合などに役立ちます。

4.8. データクラス

データ保持のみを目的としたクラスを簡潔に定義できます。equals(), hashCode(), toString(), copy(), componentN() メソッドが自動生成されます。

“`kotlin
data class Vec3i(val x: Int, val y: Int, val z: Int)

val pos1 = Vec3i(1, 2, 3)
val pos2 = Vec3i(1, 2, 3)

println(pos1 == pos2) // true (equalsが自動生成されるため値で比較)
println(pos1) // toStringが自動生成される -> Vec3i(x=1, y=2, z=3)
val pos3 = pos1.copy(y = 5) // copyメソッドで一部だけ変更して新しいインスタンスを作成
println(pos3) // Vec3i(x=1, y=5, z=3)
“`

4.9. Kotlinのファイル構成とパッケージ

Kotlinのソースファイルは .kt 拡張子を持ちます。特に理由がなければ、Javaと同様にパッケージ名とディレクトリ構造を一致させます(例: com.yourname.mykotlinmod.items パッケージの CustomItem.ktsrc/main/kotlin/com/yourname/mykotlinmod/items/CustomItem.kt に配置)。一つの .kt ファイル内に複数のクラスや関数を定義することも可能ですが、関連性の高いものをまとめるのが一般的です。

4.10. Javaコードとの連携(相互運用性)

KotlinはJavaとの相互運用性が非常に高いです。

  • KotlinからJavaを呼び出す: Javaのクラス、メソッド、フィールドは、Kotlinからそのまま呼び出すことができます。JavaのメソッドがNullablityアノテーション(@Nullable, @NonNullなど)を持っている場合、Kotlinコンパイラはそれを認識し、Null安全性をチェックしてくれます。アノテーションがない場合は「プラットフォーム型」として扱われ、NullPointerExceptionが発生する可能性があります。
  • JavaからKotlinを呼び出す: Kotlinのクラス、メソッド、プロパティは、Javaから呼び出すことができます。Kotlinのプロパティは、Javaからはgetter/setterメソッドとして見えます。Kotlinのトップレベル関数やオブジェクトのメンバーは、Javaからはスタティックメソッドとして、特定のクラス名(デフォルトではファイル名 + Kt)に格納されているように見えます。@JvmStatic, @JvmField, @JvmOverloads などのアノテーションを使うと、Javaからの見え方を調整できます。

Minecraft APIやFabric APIはJavaで書かれていますが、Kotlinから自然に利用できます。これはMod開発において大きなメリットです。

5. 基本的なModding要素の実装

いよいよ、Modで新しいコンテンツを追加する具体的な方法を見ていきましょう。まずは、最も基本的な要素であるアイテムとブロックの追加、そしてレシピの定義方法を学びます。

これらの要素を追加するには、Fabricの Registry (レジストリ) システムを使用します。レジストリは、Minecraft内の様々な要素(アイテム、ブロック、エンティティ、サウンドなど)を一元管理し、IDとそれに対応するオブジェクトを紐付ける仕組みです。新しい要素を追加するには、適切なレジストリに登録する必要があります。

5.1. アイテムの追加

新しいアイテムを追加する手順は以下の通りです。

  1. 新しいアイテムクラスを作成する。
  2. アイテムをレジストリに登録する。
  3. クリエイティブタブに追加する(任意)。
  4. 言語ファイルを設定する。
  5. テクスチャを設定する。

5.1.1. 新しいアイテムクラスの作成

src/main/kotlin/com/yourname/mykotlinmod/items/ パッケージなどに、新しいKotlinファイル CustomItem.kt を作成します。

“`kotlin
package com.yourname.mykotlinmod.items

import net.minecraft.item.Item // MinecraftのItemクラスをインポート
import net.minecraft.item.Item.Settings // Item.Settingsクラスをインポート

// Itemクラスを継承して新しいアイテムクラスを作成
class CustomItem(settings: Settings) : Item(settings) {

// 必要に応じて、アイテム独自の振る舞いをオーバーライドしたり追加したりできる
// 例: 右クリック時の動作
// override fun use(world: World, player: PlayerEntity, hand: Hand): TypedActionResult<ItemStack> {
//     player.sendMessage(Text.literal("You used the custom item!"))
//     return TypedActionResult.success(player.getStackInHand(hand))
// }

}
``ItemクラスのコンストラクタはItem.Settingsオブジェクトを引数に取ります。このSettings` オブジェクトで、アイテムのスタックサイズ上限、耐久値、エンチャント適性、修理材料などのプロパティを設定します。

5.1.2. アイテムの登録(Registryシステム)

作成したアイテムをMinecraftが認識できるように、FabricのRegistryシステムに登録します。これは通常、Modの初期化処理 (MyKotlinMod.onInitialize()) で行います。

まず、アイテムを登録するためのオブジェクトを定義します。

“`kotlin
// src/main/kotlin/com/yourname/mykotlinmod/ModItems.kt のようなファイルに記述することを推奨

package com.yourname.mykotlinmod

import com.yourname.mykotlinmod.items.CustomItem // 作成したカスタムアイテムクラスをインポート
import net.minecraft.item.Item // MinecraftのItemクラス
import net.minecraft.item.Item.Settings // Item.Settingsクラス
import net.minecraft.registry.Registries // レジストリへのアクセスに使用
import net.minecraft.registry.Registry // レジストリへのアクセスに使用
import net.minecraft.util.Identifier // リソースIDに使用

// アイテム登録処理をまとめるためのシングルトンオブジェクト
object ModItems {

// ★ アイテムのIdentifier (ネームスペース:パス) を定義
// ネームスペースは通常Mod IDを使用
// パスはアイテムのユニークな識別子 (例: custom_item)
val CUSTOM_ITEM_ID = Identifier(MyKotlinMod.MOD_ID, "custom_item")

// ★ 新しいアイテムのインスタンスを作成
// Item.Settings() でアイテムの設定を行う
// .maxCount(16) でスタックサイズを16に設定するなど
val CUSTOM_ITEM: Item = CustomItem(Settings().maxCount(16))

// ★ アイテムをレジストリに登録する関数
fun registerModItems() {
    // Registry.register() メソッドを使用して登録
    // 第1引数: 対象のレジストリ (アイテムの場合は Registries.ITEM)
    // 第2引数: アイテムのIdentifier
    // 第3引数: アイテムのインスタンス
    Registry.register(Registries.ITEM, CUSTOM_ITEM_ID, CUSTOM_ITEM)

    // 他のアイテムも同様にここで登録していく...
}

}
“`

次に、MyKotlinMod.onInitialize() メソッド内で、この登録関数を呼び出します。

“`kotlin
package com.yourname.mykotlinmod

import net.fabricmc.api.ModInitializer
import org.slf4j.LoggerFactory
import net.minecraft.util.Identifier

object MyKotlinMod : ModInitializer {

// Mod IDを定数として定義しておくと便利
const val MOD_ID = "mykotlinmod" // fabric.mod.jsonのidと一致させる

private val logger = LoggerFactory.getLogger(MOD_ID)

override fun onInitialize() {
    logger.info("Hello, Fabric world from Kotlin!")

    // ★ 作成したModItemsオブジェクトの登録関数を呼び出す
    ModItems.registerModItems()

    // TODO: 他の初期化処理
}

}
“`

これで、custom_item というIDでカスタムアイテムがゲームに登録されました。

5.1.3. ItemGroupへの追加(クリエイティブタブ)

クリエイティブインベントリのタブにアイテムを追加すると、ゲーム内で簡単に見つけられるようになります。Fabric APIの ItemGroupEvents を使用します。

これは通常、ModItems.registerModItems() のような登録処理の中で行います。

“`kotlin
package com.yourname.mykotlinmod

import com.yourname.mykotlinmod.items.CustomItem
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents // ItemGroupEventsをインポート
import net.minecraft.item.Item
import net.minecraft.item.Item.Settings
import net.minecraft.item.ItemGroups // デフォルトのItemGroupへのアクセスに使用
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.util.Identifier

object ModItems {
const val MOD_ID = MyKotlinMod.MOD_ID // Mod IDを取得

val CUSTOM_ITEM_ID = Identifier(MOD_ID, "custom_item")
val CUSTOM_ITEM: Item = CustomItem(Settings().maxCount(16))

fun registerModItems() {
    Registry.register(Registries.ITEM, CUSTOM_ITEM_ID, CUSTOM_ITEM)

    // ★ アイテムを既存のクリエイティブタブに追加
    ItemGroupEvents.modifyEntriesEvent(ItemGroups.INGREDIENTS) // 追加したいItemGroupを指定 (例: 材料タブ)
        .register { entries -> // entries はそのItemGroupのエントリリスト
            entries.add(CUSTOM_ITEM) // 作成したアイテムを追加
        }

    // 独自のクリエイティブタブを作成することも可能だが、少し複雑になるためここでは割愛
}

}
``
上記の例では、既存の「材料 (Ingredients)」タブにカスタムアイテムを追加しています。他のタブ (
ItemGroups.BUILDING_BLOCKS,ItemGroups.COMBAT` など) にも追加できます。

5.1.4. 言語ファイル(Localization)の設定

アイテム名がゲーム内で正しく表示されるように、言語ファイル(.lang または .json)を設定します。Minecraftの標準的なリソースパックの仕組みを利用します。

src/main/resources/assets/mykotlinmod/lang/en_us.json ファイルを作成します。mykotlinmod の部分はあなたのMod IDに置き換えてください。

“`json
{
// アイテム名: item.modid.itemid
“item.mykotlinmod.custom_item”: “Custom Item”,

// ブロック名 (後述): block.modid.blockid
// “block.mykotlinmod.custom_block”: “Custom Block”
}
``
キー (
item.mykotlinmod.custom_item) は固定の形式要素タイプ.ModID.アイテム/ブロックIDに従います。値 (“Custom Item”) がゲーム内に表示される名前になります。必要に応じて他の言語ファイル(ja_jp.json` など)も作成します。

5.1.5. アイテムのテクスチャ、モデルの設定

アイテムがゲーム内で表示されるためには、テクスチャとモデルが必要です。これらもリソースパックの仕組みを利用し、src/main/resources/assets/yourmodid/ ディレクトリ以下に配置します。

  • テクスチャ: src/main/resources/assets/yourmodid/textures/item/ ディレクトリに、アイテムのテクスチャ画像(通常は16×16ピクセルの.pngファイル)を置きます。ファイル名はアイテムのパスID(例: custom_item.png)にします。
  • モデル: アイテムの見た目や描画方法を定義する .json ファイルです。src/main/resources/assets/yourmodid/models/item/ ディレクトリに置きます。ファイル名はアイテムのパスID(例: custom_item.json)にします。
    簡単なアイテムの場合、通常は特定のテクスチャを参照するだけのシンプルなモデルになります。
    json
    // src/main/resources/assets/mykotlinmod/models/item/custom_item.json
    {
    "parent": "item/generated", // アイテムのデフォルトモデルを継承
    "textures": {
    "layer0": "mykotlinmod:item/custom_item" // 使用するテクスチャを指定 (modid:textures/item/texture_file_name)
    }
    }

    parentitem/generated を指定すると、インベントリや手に持ったときにテクスチャがフラットな板状で表示されるようになります。textureslayer0 は、このモデルが使用するテクスチャを指定します。値はリソースロケーション形式 (modid:textures/アイテム/テクスチャファイル名) で指定します。拡張子(.png)は含めません。

5.2. ブロックの追加

ブロックの追加も、アイテムの追加と似た手順ですが、いくつかの違いがあります。

  1. 新しいブロッククラスを作成する。
  2. ブロックアイテムを作成し、登録する。
  3. ブロック自体をレジストリに登録する。
  4. ItemGroupに追加する(任意)。
  5. 言語ファイルを設定する。
  6. テクスチャ、モデル、状態の設定をする。
  7. カスタムブロックプロパティを設定する。

5.2.1. 新しいブロッククラスの作成

src/main/kotlin/com/yourname/mykotlinmod/blocks/ パッケージなどに、新しいKotlinファイル CustomBlock.kt を作成します。

“`kotlin
package com.yourname.mykotlinmod.blocks

import net.minecraft.block.AbstractBlock // AbstractBlockクラスをインポート
import net.minecraft.block.Block // Blockクラスをインポート

// Blockクラスを継承して新しいブロッククラスを作成
// AbstractBlock.Settings() でブロックの設定を行う
class CustomBlock(settings: AbstractBlock.Settings) : Block(settings) {
// 必要に応じて、ブロック独自の振る舞いをオーバーライドしたり追加したりできる
// 例: ブロックを右クリックしたとき
// override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockHitResult): ActionResult {
// if (!world.isClient) { // サーバー側でのみ実行
// player.sendMessage(Text.literal(“You right-clicked the custom block!”), false)
// }
// return ActionResult.SUCCESS
// }
}
``BlockクラスのコンストラクタはAbstractBlock.Settingsオブジェクトを引数に取ります。このSettingsオブジェクトで、ブロックの硬さ、破壊レベル、音、マテリアル、光の透過性、当たり判定などを設定します。AbstractBlock.Settings.create()….` のようにメソッドチェーンで設定を加えていきます。

5.2.2. ブロックアイテムの作成と登録

ブロックは、インベントリ内ではアイテムとして扱われます。そのため、ブロックに対応する BlockItem クラスのインスタンスを作成し、アイテムレジストリに登録する必要があります。

“`kotlin
// src/main/kotlin/com/yourname/mykotlinmod/ModBlocks.kt のようなファイルに記述することを推奨

package com.yourname.mykotlinmod

import com.yourname.mykotlinmod.blocks.CustomBlock // 作成したカスタムブロッククラスをインポート
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings // ブロック設定を簡単に作成するためのAPI
import net.minecraft.block.Block // MinecraftのBlockクラス
import net.minecraft.block.Blocks // バニラのブロックへのアクセスに使用
import net.minecraft.item.BlockItem // ブロックに対応するアイテムクラス
import net.minecraft.item.Item.Settings // アイテム設定
import net.minecraft.registry.Registries // レジストリ
import net.minecraft.registry.Registry // レジストリ
import net.minecraft.util.Identifier // Identifier

object ModBlocks {
const val MOD_ID = MyKotlinMod.MOD_ID

// ★ ブロックのIdentifierを定義 (通常、アイテムIDと同じパスを使用)
val CUSTOM_BLOCK_ID = Identifier(MOD_ID, "custom_block")

// ★ ブロックのインスタンスを作成
// FabricBlockSettings.copyOf() を使うと既存のブロックの設定をコピーして修正できる
// .strength(4.0f) で硬さを設定 (黒曜石は50.0f)
// .requiresTool() で適切なツールが必要になるように設定
val CUSTOM_BLOCK: Block = CustomBlock(FabricBlockSettings.copyOf(Blocks.STONE).strength(4.0f).requiresTool())

// ★ ブロックに対応するアイテムのインスタンスを作成
// BlockItemのコンストラクタにブロックインスタンスとアイテム設定を渡す
val CUSTOM_BLOCK_ITEM: Item = BlockItem(CUSTOM_BLOCK, Settings())

// ★ ブロックとブロックアイテムをレジストリに登録する関数
fun registerModBlocks() {
    // ブロック自体を登録
    Registry.register(Registries.BLOCK, CUSTOM_BLOCK_ID, CUSTOM_BLOCK)
    // ブロックアイテムを登録 (Identifierはブロックと同じものを使用)
    Registry.register(Registries.ITEM, CUSTOM_BLOCK_ID, CUSTOM_BLOCK_ITEM)

    // 他のブロックも同様に登録...
}

}
``FabricBlockSettings.copyOf(Blocks.STONE)は、石ブロックの設定をコピーしてくる便利な方法です。そこからstrength()` などのメソッドを使って必要な設定変更を行います。

5.2.3. ブロックの登録

上記 ModBlocks.registerModBlocks() 関数の Registry.register(Registries.BLOCK, CUSTOM_BLOCK_ID, CUSTOM_BLOCK) 行で行われます。

5.2.4. ItemGroupへの追加

ブロックアイテムも、アイテムと同様にクリエイティブタブに追加できます。

kotlin
// ModBlocks.registerModBlocks() 関数内に追記
ItemGroupEvents.modifyEntriesEvent(ItemGroups.BUILDING_BLOCKS) // 建築ブロックタブに追加する場合
.register { entries ->
entries.add(CUSTOM_BLOCK_ITEM) // ブロックアイテムを追加
}

5.2.5. 言語ファイルの設定

アイテムと同様に、en_us.json などの言語ファイルにブロック名を追加します。

json
{
"item.mykotlinmod.custom_item": "Custom Item",
"block.mykotlinmod.custom_block": "Custom Block" // キーは "block.modid.blockid"
}

5.2.6. テクスチャ、モデル、状態の設定

ブロックの見た目を定義するには、テクスチャ、モデル、そしてブロックの状態(Block State)を記述するファイルが必要です。

  • テクスチャ: src/main/resources/assets/yourmodid/textures/block/ ディレクトリに、ブロックのテクスチャ画像(通常は16×16ピクセルの.pngファイル)を置きます。ファイル名はブロックのパスID(例: custom_block.png)にします。
  • モデル: ブロックの形状を定義する .json ファイルです。src/main/resources/assets/yourmodid/models/block/ ディレクトリに置きます。ファイル名はブロックのパスID(例: custom_block.json)にします。
    シンプルなキューブ状のブロックの場合、全方向同じテクスチャを使用するモデルは以下のように定義します。
    json
    // src/main/resources/assets/mykotlinmod/models/block/custom_block.json
    {
    "parent": "block/cube_all", // 全方向同じテクスチャのキューブモデルを継承
    "textures": {
    "all": "mykotlinmod:block/custom_block" // 使用するテクスチャを指定 (modid:textures/block/texture_file_name)
    }
    }

    parentblock/cube_all を指定し、texturesall で使用するテクスチャを指定します。
  • ブロック状態 (Block State): 特定のブロックIDを持つブロックが、ワールド内に設置されたときにどのようなモデルを使用するかを定義する .json ファイルです。src/main/resources/assets/yourmodid/blockstates/ ディレクトリに置きます。ファイル名はブロックのパスID(例: custom_block.json)にします。
    状態を持たないシンプルなブロックの場合、以下のように定義します。
    json
    // src/main/resources/assets/mykotlinmod/blockstates/custom_block.json
    {
    "variants": {
    "": { "model": "mykotlinmod:block/custom_block" } // 状態なし ("") の場合、指定したモデルを使用
    }
    }

    variants オブジェクトは、ブロックの状態(例えば、向きや水に濡れているかなど)に応じて使用するモデルを切り替えるために使用します。状態がないシンプルなブロックでは、空文字列 "" をキーとして指定します。値は使用するモデルのリソースロケーション (modid:models/block/model_file_name) です。

これで、新しいカスタムブロックがゲームに追加され、設置や破壊ができるようになります。

5.3. レシピの追加

追加したアイテムやブロックをクラフトなどで作成できるように、レシピを定義します。レシピは、データパックの形式で src/main/resources/data/yourmodid/recipes/ ディレクトリ以下に .json ファイルとして配置するのが標準的な方法です。yourmodid の部分はあなたのMod IDに置き換えてください。

レシピには主に2つの種類があります。

  • Shaped Recipe (形のあるレシピ): クラフトグリッド内のアイテムの配置が重要なレシピ(例: ツルハシ、チェストなど)。
  • Shapeless Recipe (形の無いレシピ): クラフトグリッド内のアイテムの配置が関係ないレシピ(例: 染料、雪玉など)。

5.3.1. Shaped Recipeの追加

src/main/resources/data/mykotlinmod/recipes/ ディレクトリに、レシピを定義する .json ファイルを作成します。ファイル名は任意ですが、作成するアイテム/ブロックのIDに合わせるのが一般的です(例: custom_item.json)。

“`json
// src/main/resources/data/mykotlinmod/recipes/custom_item.json
{
“type”: “minecraft:crafting_shaped”, // レシピの種類を指定 (shaped crafting)

“pattern”: [ // クラフトグリッドのパターンを定義 (3×3まで)
“III”,
” S “,
” S ”
],

“key”: { // パターンで使用する文字とアイテム/ブロックの対応関係を定義
“I”: {
“item”: “minecraft:iron_ingot” // 鉄インゴット
},
“S”: {
“item”: “minecraft:stick” // 棒
}
},

“result”: { // 完成するアイテム/ブロックを指定
“item”: “mykotlinmod:custom_item”, // Mod ID:アイテムID
“count”: 1 // 作成される個数
}
}
“`
このレシピは、クラフト台の上段に鉄インゴット3つ、中断と下段の中央に棒を配置すると、カスタムアイテムが1つ作成されることを定義しています。

5.3.2. Shapeless Recipeの追加

形の無いレシピはよりシンプルに定義できます。

“`json
// src/main/resources/data/mykotlinmod/recipes/another_custom_item_shapeless.json
{
“type”: “minecraft:crafting_shapeless”, // レシピの種類を指定 (shapeless crafting)

“ingredients”: [ // 材料のリストを定義 (配置は問わない)
{
“item”: “minecraft:apple” // リンゴ
},
{
“item”: “minecraft:sugar” // 砂糖
},
{
“item”: “mykotlinmod:custom_item” // カスタムアイテム
}
],

“result”: { // 完成するアイテム/ブロックを指定
“item”: “mykotlinmod:another_custom_item”, // 別のカスタムアイテムID
“count”: 2 // 作成される個数
}
}
“`
このレシピは、リンゴ1つ、砂糖1つ、カスタムアイテム1つをクラフトグリッドのどこかに配置すると、別のカスタムアイテムが2つ作成されることを定義しています。

5.3.3. 製錬レシピの追加

かまどなどで製錬するレシピも定義できます。

“`json
// src/main/resources/data/mykotlinmod/recipes/smelt_custom_ore.json
{
“type”: “minecraft:smelting”, // レシピの種類を指定 (smelting)

“ingredient”: { // 材料を指定
“item”: “mykotlinmod:custom_ore_block” // カスタム鉱石ブロックID
},

“result”: “mykotlinmod:custom_ingot_item”, // 完成するアイテム/ブロックを指定
“experience”: 0.7, // 獲得経験値量
“cookingtime”: 200 // 製錬にかかる時間 (ティック, 20ティック = 1秒)
}
“`
このレシピは、カスタム鉱石ブロックをかまどで製錬すると、カスタムインゴットアイテムが作成されることを定義しています。

データパック形式のレシピは、Modをゲームにロードする際にFabric Loaderによって自動的に読み込まれます。特別な登録コードは不要です。

6. イベントとフック

Minecraftの世界は様々なイベントで動いています。ブロックの設置/破壊、プレイヤーの移動、エンティティのスポーン、ティックの進行など、あらゆるアクションや状態変化がイベントとして発生します。Modがこれらのイベントを「待ち受け」て、特定のイベントが発生したときに独自の処理を実行する仕組みがイベントハンドリングです。

Fabricでは、Fabric APIが提供する Event API を使用するのが一般的です。

6.1. FabricのEvent APIの仕組み

FabricのEvent APIは、Observerパターンに基づいています。

  • Event: 特定の種類のイベントを表すオブジェクトです。Fabric APIには様々な組み込みイベントが用意されています(例: PlayerBlockEvents, ServerTickEvents)。
  • Listener: イベントが発生したときに実行されるコード(関数やメソッド)です。特定のイベントタイプに対応するインターフェースを実装します。
  • Event Emitter: イベントを発生させる側です。Minecraftのコードがイベントを発生させると、Event APIを通じて登録されている全てのListenerに通知されます。

開発者は、特定のイベントタイプに対応するListenerインターフェースを実装したコードを作成し、そのListenerをEventに登録します。

6.2. よく使われるイベント

Fabric APIは非常に多くのイベントを提供しています。代表的なものをいくつか挙げます。

  • ServerTickEvents.END_SERVER_TICK: サーバーのティック処理の最後に毎ティック呼び出される。
  • ClientTickEvents.END_CLIENT_TICK: クライアントのティック処理の最後に毎ティック呼び出される。
  • PlayerBlockEvents.BEFORE_BREAK: プレイヤーがブロックを破壊する直前に呼び出される。
  • PlayerBlockEvents.AFTER_BREAK: プレイヤーがブロックを破壊した直後に呼び出される。
  • PlayerBlockEvents.BEFORE_PLACE: プレイヤーがブロックを設置する直前に呼び出される。
  • PlayerBlockEvents.AFTER_PLACE: プレイヤーがブロックを設置した直後に呼び出される。
  • UseBlockEvents.BEFORE: プレイヤーがブロックを右クリックする直前に呼び出される。
  • UseItemEvents.BEFORE: プレイヤーがアイテムを使用する直前に呼び出される。
  • AttackEntityEvents.ALLOW: プレイヤーがエンティティを攻撃できるか判定する際に呼び出される。
  • ServerLifecycleEvents.SERVER_STARTING: サーバーが起動を開始したときに呼び出される。
  • ServerLifecycleEvents.SERVER_STARTED: サーバーが完全に起動したときに呼び出される。
  • ServerLifecycleEvents.SERVER_STOPPING: サーバーが停止を開始したときに呼び出される。
  • ServerLifecycleEvents.SERVER_STOPPED: サーバーが完全に停止したときに呼び出される。

これらのイベントは、Modの初期化処理 (onInitialize()) の中で登録します。

6.3. イベントリスナーの登録方法

イベントリスナーを登録するには、対象のEventオブジェクトの register() メソッドを使用します。register() メソッドは、通常、対応するListenerインターフェースのインスタンスを引数に取ります。

Kotlinでは、SAM (Single Abstract Method) 変換やオブジェクト式、ラムダ式を使用することで、より簡潔にリスナーを記述できます。

6.3.4. イベントハンドリングの実践例:プレイヤーが右クリックしたときにメッセージを表示

プレイヤーが特定のブロックを右クリックしたときにメッセージを表示するModを実装してみましょう。UseBlockEvents.BEFORE イベントを使用します。

“`kotlin
package com.yourname.mykotlinmod

import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.event.player.UseBlockEvents // 使用するイベントをインポート
import net.minecraft.text.Text // ゲーム内メッセージ表示に使用
import org.slf4j.LoggerFactory

object MyKotlinMod : ModInitializer {
const val MOD_ID = “mykotlinmod”
private val logger = LoggerFactory.getLogger(MOD_ID)

override fun onInitialize() {
    logger.info("Hello, Fabric world from Kotlin!")

    // アイテムとブロックの登録 (前のセクションで実装した関数)
    ModItems.registerModItems()
    ModBlocks.registerModBlocks()

    // ★ イベントリスナーの登録
    // UseBlockEvents.BEFORE イベントにリスナーを登録
    UseBlockEvents.BEFORE.register { player, world, hand, hitResult ->
        // ラムダ式の引数: player, world, hand, hitResult (これらはイベントの種類によって異なる)

        // サーバー側でのみ処理を実行 (クライアント側でもイベントは発生するが、ゲームロジックはサーバーで行うべき)
        if (!world.isClient) {
            val clickedBlockPos = hitResult.blockPos // クリックされたブロックの座標
            val clickedBlockState = world.getBlockState(clickedBlockPos) // クリックされたブロックの状態
            val clickedBlock = clickedBlockState.block // クリックされたブロック自体

            // 例: クリックされたブロックがバニラのストーンブロックの場合
            if (clickedBlock == net.minecraft.block.Blocks.STONE) {
                // プレイヤーにメッセージを送信
                player.sendMessage(Text.literal("You right-clicked a stone block at $clickedBlockPos!"), false)
                logger.info("Player ${player.name.string} right-clicked stone at $clickedBlockPos")
            }

            // TODO: ここで特定のカスタムブロックをチェックすることもできる
            // if (clickedBlock == ModBlocks.CUSTOM_BLOCK) { ... }
        }

        // ActionResultを返す
        // ActionResult.PASS: イベントを次のリスナーやバニラの処理に渡す
        // ActionResult.FAIL: イベントをキャンセルする
        // ActionResult.CONSUME: イベントを消費し、バニラの処理に進まない (クライアント側で視覚的なフィードバックを抑制したい場合など)
        // ActionResult.SUCCESS: イベントを成功として処理し、バニラの処理に進まない (ただし、通常はPASS/FAIL/CONSUMEを使用)

        net.minecraft.util.ActionResult.PASS // このイベント後もバニラのブロック使用処理を続行する
    }

    logger.info("Block Use Event Listener Registered!")
}

}
``
*
UseBlockEvents.BEFORE.register { … }のように、イベントオブジェクトのregisterメソッドにラムダ式を渡すことでリスナーを登録できます。ラムダ式の引数(player,world,hand,hitResult)は、そのイベントタイプが提供する情報です。
*
!world.isClientでサーバー側の処理であることを確認しています。Minecraftの多くのゲームロジックはサーバー側で実行されるため、Modの振る舞いを変更する処理はサーバー側で行うべきです。クライアント側は見た目の処理(GUI表示など)に特化します。
*
hitResult.blockPosでクリックされたブロックの座標、world.getBlockState(pos)でその座標のブロックの状態を取得し、.blockでブロックオブジェクトを取得しています。
*
player.sendMessage()でプレイヤーにメッセージを送信します。Text.literal()でシンプルなテキストメッセージを作成できます。第2引数のfalseは、チャット履歴には残さずに画面下部に短時間表示するメッセージであることを意味します。
* イベントリスナーは、イベント処理の結果を示す
ActionResultを返します。PASSはイベントをそのまま後続の処理に流すことを意味します。FAILCONSUME` を返すと、イベントがキャンセルされたり、バニラの処理がスキップされたりします。

このコードを追加してModをビルド・実行し、ゲーム内でストーンブロックを右クリックしてみてください。画面下部にメッセージが表示されるはずです。

7. 高度なModding要素

Mod開発は、アイテムやブロックの追加だけに留まりません。より複雑な機能を実現するための要素も見ていきましょう。ここでは概念的な説明と、簡単な実装の方向性を示します。

7.1. エンティティの追加

独自のMOBや乗り物、特殊な効果を持つ弾など、ワールド内に存在する動的なオブジェクトを追加するのがエンティティ開発です。

  • カスタムエンティティクラスの作成: net.minecraft.entity.Entity クラスやそのサブクラス(例: MobEntity, AnimalEntity, ProjectileEntity)を継承して、新しいエンティティクラスを作成します。エンティティの挙動(移動、攻撃、AI、描画など)を実装します。
  • エンティティの種類の登録: net.minecraft.entity.EntityType を作成し、エンティティレジストリ (Registries.ENTITY_TYPE) に登録します。この EntityType オブジェクトに、エンティティのファクトリ関数(インスタンスを作成する方法)、寸法、スポーン設定などを紐付けます。
  • スポーン設定: Mobの場合、特定のバイオームや条件で自然にスポーンするように設定したり、スポーンエッグアイテムを追加したりします。Fabric APIの FabricDefaultAttributeRegistrySpawnRestrictionRegistryBiomeModifications などを使用します。
  • レンダリング: クライアント側では、エンティティを画面に描画するためのレンダラー(net.minecraft.client.render.entity.EntityRenderer)が必要です。エンティティレンダラーをエンティティタイプと紐付けて登録します。Fabric APIの EntityRendererRegistry を使用します。

エンティティ開発はブロックやアイテムよりも複雑で、アニメーション、AI、ネットワーク同期など、多くの側面を考慮する必要があります。

7.2. コマンドの追加

プレイヤーがチャットで特定のコマンドを入力してModの機能を実行できるようにします。Minecraftはコマンド処理に Brigadier というライブラリを使用しており、Fabricもこれを活用します。

  • コマンドの登録: Modの初期化時やサーバー起動時イベントなどで、コマンドをコマンドレジストリに登録します。Fabric APIの CommandRegistrationCallback イベントを使用します。
  • コマンドノードの定義: BrigadierのAPIを使って、コマンド名、引数、サブコマンド、実行ロジックをツリー構造で定義します。例えば、/mycommand <player> set_value <value> のようなコマンド構造を定義します。
  • コマンド実行ロジックの実装: コマンドが入力されたときに実際に実行されるコードを記述します。これは通常、コマンド実行のコンテキスト(どのプレイヤーが実行したか、引数の値など)を受け取るラムダ式やメソッドとして実装します。

コマンドを追加することで、Modのデバッグを容易にしたり、管理者向けの機能を提供したり、ゲームプレイを制御する手段を提供したりできます。

7.3. GUI/スクリーン

プレイヤーがインベントリ画面や特定のブロックを右クリックした際に表示される独自のGUI (Graphical User Interface) を作成します。

  • スクリーンクラスの作成: クライアント側でGUIの見た目を定義するクラスです。net.minecraft.client.gui.screen.Screen またはそのサブクラスを継承します。ボタン、テキストフィールドなどのウィジェットを配置し、描画や入力処理を実装します。
  • コンテナ/スクリーンハンドラー: インベントリやクラフト台のように、アイテムのやり取りがあるGUIの場合、クライアント(Screen)とサーバーの間でアイテムの状態やプレイヤーの操作を同期させるためのサーバー側コンポーネントが必要です。これは net.minecraft.screen.ScreenHandler クラスを継承して作成します。
  • GUIの表示: イベント(例: 特定のアイテムを使用、ブロックを右クリック)をトリガーとして、クライアント側でスクリーンを表示します。MinecraftClient.getInstance().setScreen(MyScreen(...)) のように呼び出します。アイテムのやり取りがある場合は、サーバー側で ScreenHandler を開き、クライアントにパケットを送信して対応する Screen を開かせます。
  • 登録: カスタム ScreenHandlerRegistries.SCREEN_HANDLER に登録が必要です。Fabric APIの ScreenHandlerRegistry を使用すると便利です。

GUI開発は、クライアントとサーバー間の同期や、ウィジェットの配置・描画など、フロントエンド開発に近い側面があり、比較的複雑なトピックです。

7.4. ネットワーク通信

クライアントとサーバー間でMod固有の情報をやり取りしたい場合があります。例えば、Modの設定をサーバーからクライアントに送信したり、クライアントの操作をサーバーに伝えたりする際などに必要になります。

  • Custom Payload Packets: Fabricでは、Mod独自のデータを含むカスタムパケットを送受信する仕組みが提供されています。特定の Identifier をチャンネルとして使用し、バイトデータをやり取りします。
  • Packet Sender/Receiver: クライアント側とサーバー側でそれぞれパケットを送信 (PacketByteBuf を使ってデータを書き込む) および受信 (PacketByteBuf を使ってデータを読み出す) するコードを実装します。
  • 登録: Fabric APIの ServerPlayNetworking (サーバー側) や ClientPlayNetworking (クライアント側) を使用して、指定したチャンネルでパケットを受信した際のハンドラーを登録します。

7.5. コンフィグレーション

Modの設定を外部ファイルから読み込んだり、ゲーム内で設定画面を提供したりする機能です。

  • 設定クラスの定義: Modの設定項目(数値、真偽値、文字列など)を持つデータクラスなどを定義します。
  • 設定ファイルの読み書き: 設定クラスのインスタンスをファイル(通常はJSONやTOMLなどの形式)に保存・読み込みするロジックを実装します。JavaのファイルI/Oや、GsonなどのJSONライブラリを使用します。
  • 設定画面: Fabric APIやCloth Config APIなどの外部ライブラリを使用すると、Mod設定画面を簡単に作成できます。Cloth Config APIは非常に高機能で、設定値を自動的にファイルに保存・読み込みしたり、設定値を変更した際にイベントを発生させたりできます。

8. データ駆動型開発

Minecraftは多くの要素をデータパックやリソースパックという形で外部ファイルからロードする仕組みを持っています。Mod開発においても、この仕組みを活用することで、コードの量を減らしたり、設定の変更を容易にしたりできます。

8.1. データパック

データパックは、レシピ、ロートテーブル、進捗、構造物、タグ、ワールド生成設定など、ゲームのロジックやコンテンツに関わるデータを定義するものです。Modのリソースディレクトリ (src/main/resources/data/yourmodid/) に配置したJSONファイルなどがデータパックとして認識されます。

  • レシピ: 前述の通り、アイテムやブロックのレシピはデータパック (data/yourmodid/recipes/) として追加するのが標準です。
  • ロートテーブル: ブロックを破壊したとき、エンティティを倒したとき、チェストを開けたときなどにドロップするアイテムを定義します (data/yourmodid/loot_tables/...)。
  • 進捗 (Advancements): ゲームの目標や進行状況を示す進捗ツリーを定義します (data/yourmodid/advancements/...)。
  • タグ (Tags): アイテム、ブロック、エンティティなどをグループ化し、特定のグループに属するかどうかを判定できるようにします。例えば、特定のタグを持つ全てのブロックに対して処理を行いたい場合などに使用します (data/yourmodid/tags/...)。Modコード内でタグを参照できます。

データパックとして定義されたコンテンツは、ゲーム起動時やデータパックのリロード時に自動的に読み込まれます。Modのコード内で明示的に登録する必要はありません(ただし、カスタム要素を参照する際には、その要素がデータパックで定義されていることを前提とするコードが必要になります)。

8.2. リソースパック

リソースパックは、テクスチャ、モデル、サウンド、言語ファイルなど、ゲームの見た目や音に関わるデータを定義するものです。Modのリソースディレクトリ (src/main/resources/assets/yourmodid/) に配置したファイルなどがリソースパックとして認識されます。

  • テクスチャ、モデル、ブロック状態: 前述の通り、アイテムやブロックの見た目はリソースパック (assets/yourmodid/...) として追加するのが標準です。
  • 言語ファイル: ゲーム内のテキスト(アイテム名、ブロック名、進捗名など)を定義します (assets/yourmodid/lang/)。
  • サウンド: Mod独自のサウンドエフェクトやBGMを追加できます (assets/yourmodid/sounds.json および assets/yourmodid/sounds/...)。

リソースパックとして定義されたコンテンツは、ゲーム起動時やリソースパックのリロード時に自動的に読み込まれます。

8.3. Modとデータパック/リソースパックの連携

Mod開発において、コードで新しいクラス(カスタムアイテム、カスタムブロックなど)を定義し、その定義した要素をデータパック/リソースパックで参照して見た目やレシピを設定するというのが一般的な流れです。

例えば、Kotlinコードで CustomItem クラスを定義し、レジストリに登録します。そして、データパックで custom_item.json レシピファイルを定義し、その中で "item": "mykotlinmod:custom_item" のように、コードで登録したアイテムIDを参照します。同様に、リソースパックで custom_item.json モデルファイルや custom_item.png テクスチャを定義し、"mykotlinmod:item/custom_item" のように参照します。

このように、コードとデータ/リソースを適切に分離することで、Modの構造を整理し、管理しやすくすることができます。

9. デバッグとトラブルシューティング

Mod開発は常にスムーズに進むとは限りません。予期せぬエラーや望まない挙動に遭遇した場合、原因を特定し修正するためのデバッグスキルが重要になります。

9.1. IDEでのデバッグ方法

IntelliJ IDEAのような高機能IDEは、デバッグを強力にサポートします。

  1. ブレークポイントの設定: コードの実行を一時停止したい行の左側のガター(行番号が表示されている領域)をクリックすると、赤い丸のブレークポイントを設定できます。
  2. デバッグモードでの実行: Gradleツールウィンドウで runClientrunServer タスクを右クリックし、「Debug」を選択します。または、Run/Debug Configurationsからデバッグ設定を作成し実行します。
  3. デバッグの操作:
    • コードがブレークポイントで停止すると、画面下部にDebugウィンドウが表示されます。
    • Variablesウィンドウで、その時点での変数の値を確認できます。
    • Consoleウィンドウで、Modが出力したログやエラーメッセージを確認できます。
    • Step Over (F10またはCmd+F10): 現在の行を実行し、次の行に進みます。関数呼び出しがあっても関数の中には入りません。
    • Step Into (F11またはCmd+F11): 現在の行を実行し、関数呼び出しがあればその関数の中に入ります。
    • Step Out (Shift+F11): 現在の関数から抜け出し、呼び出し元の次の行に進みます。
    • Resume Program (F9またはCmd+F9): 次のブレークポイントまでコードの実行を再開します。
    • Stop (赤い四角): デバッグセッションを終了します。

デバッグモードでゲームを実行し、Modの機能を使用するなどしてブレークポイントにヒットさせると、コードの実行を止め、その時点でのプログラムの状態を詳しく調べることができます。これにより、変数の値が期待通りか、特定のコードブロックが実行されているかなどを確認できます。

9.2. ログの確認 (latest.log)

Minecraftサーバーやクライアントは、実行中に様々な情報やエラーをログファイルに出力します。Mod開発においては、このログファイルがデバッグの重要な手がかりとなります。

  • ログファイルは、Minecraftの実行ディレクトリ(runClientrunServer タスクで起動した場合、通常はプロジェクトディレクトリの .gradle/loom-cache/run/<run_config_name>/ 以下に生成されるワールドディレクトリ内の logs/latest.log)に保存されます。
  • IntelliJ IDEAのRunウィンドウにも、ゲームのログがリアルタイムで表示されます。
  • org.slf4j.Logger を使用してMod独自のログメッセージを適切に出力することで、問題発生時の状況把握が容易になります。例えば、重要な処理の開始/終了や、変数の値などをログに出力しておくと役立ちます。

エラーが発生した場合、ログファイルの末尾を見ると、エラーの種類 (NullPointerException, IllegalArgumentException など) や、エラーが発生したコードの場所(スタックトレース)が記録されています。スタックトレースを上から順にたどっていくと、Modのコード内でエラーを引き起こした箇所を特定できます。

9.3. 一般的なエラーとその対処法

  • NullPointerException (NPE): Nullableな変数が null であるにも関わらず、そのメンバーにアクセスしようとした場合に発生します。KotlinではNull安全性の機能で多くのNPEを防げますが、Java APIとの連携時や !! 演算子の使用時に発生する可能性があります。原因箇所の変数やオブジェクトがなぜ null になっているのか、期待する値が入る条件は何かを確認します。安全呼び出し ?. やElvis演算子 ?: を適切に使用することで対処できます。
  • IllegalArgumentException / IllegalStateException: メソッドの引数が不正な場合や、オブジェクトの状態が不正な場合に発生します。エラーメッセージに原因が示されていることが多いです。メソッドのJavadocを確認したり、呼び出し元のコードで引数やオブジェクトの状態をチェックしたりして対処します。
  • Registry関連のエラー: アイテムやブロックなどが正しく登録されていない場合、IDが重複している場合などに発生します。ログに「Unregistered object」などのメッセージが表示されることがあります。fabric.mod.json のMod IDとコード内のIdentifierが一致しているか、Registry.register() が適切なタイミング(通常は onInitialize()) で呼び出されているかを確認します。
  • Resource Loading関連のエラー: テクスチャ、モデル、言語ファイルなどのリソースファイルが見つからない場合に発生します。ログに「Could not find asset」などのメッセージと、期待されるリソースのパスが表示されます。src/main/resources/assets/yourmodid/... 以下にファイルが正しく配置されているか、ファイル名やディレクトリ構造がIdentifierに対応しているか、JSONファイルの構文が正しいかなどを確認します。Mod IDとリソースディレクトリ名が一致しているかも重要です。

9.4. コミュニティリソースの活用

一人で問題を解決できない場合は、コミュニティの助けを借りましょう。

  • Fabric Discord: Fabric Moddingの公式Discordサーバーは、質問したり他の開発者と交流したりするのに最適な場所です。困ったときは #modding-help チャンネルなどで質問してみてください。エラーメッセージや関連するコード、latest.log の内容などを添えると、より的確な助けが得られます。
  • Fabric Wiki: Fabric Mod開発に関する公式ドキュメントやチュートリアルが豊富に掲載されています。多くの情報はこちらで確認できます。
  • Stack Overflow: プログラミングに関する質問と回答のサイトです。Minecraft ModdingやKotlinに関する質問も多く投稿されています。

10. ベストプラクティス

より良いModを開発するために、いくつかのベストプラクティスを心掛けましょう。

  • Mod IDとネームスペースの重要性: Mod IDはあなたのModを識別するユニークなIDです。fabric.mod.json で設定し、リソースファイル(テクスチャ、モデル、言語ファイル、レシピなど)やRegistryのIdentifierのネームスペースとして使用します。他のModとの競合を避けるため、あなたの名前やニックネームを含むユニークなID(例: yourname_coolmod)を使用することを強く推奨します。全てのカスタム要素(アイテム、ブロック、エンティティ、GUIなど)には、このMod IDをネームスペースとしたIdentifier (modid:item_id) を使用します。
  • コードの整理と可読性:
    • 関連するコードは適切なパッケージ(例: com.yourname.mykotlinmod.items, com.yourname.mykotlinmod.blocks, com.yourname.mykotlinmod.events)に分けましょう。
    • 大きなファイルは複数のファイルに分割しましょう(例: アイテム登録は ModItems.kt に、ブロック登録は ModBlocks.kt にまとめる)。
    • 変数名、関数名、クラス名などは、その役割が分かりやすい名前をつけましょう。Kotlinでは、プロパティ名や関数名にキャメルケース(例: myCustomItem)を使用するのが一般的です。定数には全て大文字のスネークケース(例: CUSTOM_ITEM_ID)を使用することが多いです。
    • 適切なコメントやドキュメンテーション(KDoc)を記述しましょう。
  • バージョニングの戦略: Modのバージョン番号は、Modの変更内容や互換性を示すために重要です。セマンティックバージョニング(例: Major.Minor.Patch)に従うのが一般的です。
    • Major: 後方互換性のない大きな変更
    • Minor: 後方互換性のある新機能の追加
    • Patch: 後方互換性のあるバグ修正や小さな改善
      また、対応するMinecraftのバージョンやFabric Loaderのバージョンを明確にすることも重要です。fabric.mod.jsondepends セクションで適切なバージョン範囲を指定しましょう。
  • 互換性への配慮:
    • Fabric APIに用意されているAPIやイベントを積極的に利用しましょう。Minecraft本体の内部実装(混同しやすいものにアノテーションが付いていることが多い)に直接依存するコードは、Minecraftのアップデートで壊れやすいため避けるべきです。
    • 他のModとの競合を避けるため、前述のMod IDとネームスペースを適切に使用しましょう。
    • 可能であれば、他のModがあなたのModの機能を利用できるようにAPI(別途Jarとしてビルドするなど)を提供することも検討しましょう。
  • パフォーマンスの考慮: 特にTickイベントなど、頻繁に呼び出される処理では、重い処理(例: 広範囲のブロック走査、複雑な計算)を実行しないように注意が必要です。プロファイリングツールを使って、Modのボトルネックを特定することも有効です。

11. Modの配布

Modが完成したら、他のプレイヤーに配布できるように準備します。

11.1. ビルド成果物の確認

gradlew build タスクを実行してビルドすると、プロジェクトディレクトリ内の build/libs/ ディレクトリに配布可能なMod Jarファイルが出力されます(例: mykotlinmod-1.0.0.jar)。このファイルが、他のプレイヤーがMinecraftの mods フォルダに入れるべきファイルです。ファイルサイズや内容を確認し、不要なファイル(開発用のデバッグ情報など)が含まれていないことを確認しましょう(通常、Fabric Loomが適切に設定されていれば問題ありません)。

11.2. ModrinthやCurseForgeへのアップロード方法

Modの配布先としては、Modrinth (modrinth.com) や CurseForge (curseforge.com) が主要なプラットフォームです。これらのサイトを利用すると、多くのプレイヤーにModを見つけてもらいやすくなります。

  1. 各サイトでアカウントを作成します。
  2. 新しいプロジェクト(Mod)を作成します。Mod名、説明、アイコン、スクリーンショットなどを設定します。
  3. ファイルをアップロードします。ここでビルドした配布用Jarファイル (mykotlinmod-1.0.0.jar) をアップロードします。
  4. アップロード時に、Modが対応するMinecraftのバージョン、Modローダー(Fabric)、必要な依存関係(Fabric APIなど)を指定します。
  5. 承認プロセスを経て、Modが公開されます。

プロジェクトページには、Modのインストール方法(Fabric Loaderのインストール、Modファイルの mods フォルダへの配置)や、Modの使用方法などを分かりやすく記述しておきましょう。

11.3. ライセンスの選択

開発したModを公開する際は、どのような条件で他の人があなたのModを利用・改変・配布できるかを定めるライセンスを選択することを推奨します。オープンソースライセンス(MIT License, Apache License 2.0, GNU GPLなど)を選択するのが一般的です。fabric.mod.jsonlicense フィールドにライセンスIDを記述し、プロジェクトのリポジトリに LICENSE ファイルを置くのが標準的な方法です。

12. 次のステップ

本ガイドで学んだことは、Minecraft Mod開発の基礎にすぎません。ここからさらに複雑でオリジナリティのあるModを開発していくための道は無限に広がっています。

  • さらに複雑な機能の実装: GUI付きのカスタムブロック(機械など)、独自のバイオームやディメンション、カスタム構造物、ワールド生成の改変など、より高度なModdingトピックに挑戦してみましょう。
  • 他のModとの連携(APIの使用): 一部のModは、他のModから利用できるAPIを提供しています。例えば、エネルギーシステム(Power API)、ストレージシステム(Trinketsなど)、レンダーAPI(Canvasなど)といったFabric API以外の外部APIを利用することで、他のModと連携したり、よりリッチな機能を実現したりできます。利用したいModのドキュメントやAPIを確認しましょう。
  • コミュニティへの貢献: FabricやFabric API、他のModのソースコードを読んで、より深い理解を得ることができます。バグを見つけたら報告したり、修正のプルリクエストを送ったり、ドキュメントの改善に協力したりと、オープンソースコミュニティに貢献することも素晴らしい経験になります。
  • シェーダー、パーティクル、サウンドなどのカスタマイズ: リソースパックの仕組みをさらに活用して、ゲームの視覚や聴覚をカスタマイズしてみましょう。

Mod開発の旅に終わりはありません。常に新しいことを学び、試行錯誤を繰り返しながら、あなたの創造性を形にしていきましょう。

13. まとめ

本ガイドでは、Minecraft Mod開発をKotlinとFabricで始めるための道のりを、環境構築から基本的なアイテム・ブロックの追加、イベントハンドリング、そして高度なトピックの概要まで、詳細に解説しました。

Kotlinのモダンな機能とJavaとの相互運用性、Fabricの軽量かつ柔軟な特性は、Mod開発をより楽しく、効率的にしてくれます。Registryシステム、Event API、データ駆動型開発といったFabric Moddingの基本的な概念を理解し、アイテムやブロックの追加といった具体的なステップを経験したことで、あなたはMod開発の確かな一歩を踏み出しました。

Mod開発は挑戦的なプロセスですが、あなたが想像したものがゲームの世界に実際に現れる瞬間の喜びは格別です。このガイドが、あなたの素晴らしいMod開発の旅の出発点となり、Minecraftの世界をさらに豊かにするユニークなModを生み出す助けとなることを願っています。

さあ、あなただけのModを世界に送り出しましょう!


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール