Javaは分からないけどマイクラMODを作りたい #5 EntityPlayer を継承すると描画クラスでエラーが起こる話

今回から人間ユニットの動作部分(機能部分)の製作に当たります。今後、動作部分のことをAIと呼びます。AIを作る際には entity ディレクトリ内に ai というディレクトリを作成し、その中に書いていきます。

1. ディレクトリ構成の確認

まず、今までに作っていたディレクトリを再度確認します。

  • ~/takunologymod: メインディレクトリでMod全体の名称。

  • takunologymod/entity : Entity に関する内容をまとめるディレクトリ。

  • takunologymod/init :FML (Forge Mod Loader) にてMod初期化処理を行う際のデータ登録をまとめる。今回は Enitty の登録を管理するディレクトリになっている。今後、アイテムやブロックなどを増やす場合はこの中に登録用クラスとして付け足していく。

  • takunology/util :追加事項のあるものを管理するディレクトリ。(今回はレンダラーのイベント初期化処理で使用している。)

ここまでが大まかなディレクトリです。ここからは takunologymod/entity ディレクトリ内の配置についてです。

  • entity/ai : Entity の機能を記述するディレクトリ。動作内容や作業(タスク) 内容の定義で使用。

  • entity/model Entity の形状を管理するディレクトリ。テクスチャを貼り付けるための胴体に関する定義部分。

  • entity/render : Entity の描画レンダリング)を管理するディレクトリ。テクスチャを読み込んで model に貼り付けるための画像を return する。

前回までに modelrender は定義済みですね。意外と少ないディレクトリ構成で生物は生み出せることが分かったのですが、ここから色々と付け足していく予定です。

上記のディレクトリ構成で作業を進めていきます。

2. PlayerEntityの継承

プレイヤーと同じ構造にしたいので、継承内容を変更します。entity 直下に HumanUnit がありますが、これは基本ベースとなるクラスです。今の段階では EntityVillager を継承したままなので、これを EntityPlayer に変更します。

変更するとスーパークラスへ渡すコンストラクタの引数も変わるので、super メソッドを変更しなければなりません。ということで、変更してみました。

package jp.takunology.takunologymod.entity;

import com.mojang.authlib.GameProfile;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;

//プレイヤーベース Entity の継承
public class HumanUnit extends EntityPlayer {

    public HumanUnit(World worldIn, GameProfile gameProfile)
    {
        super(worldIn, gameProfile);
    }

    @Override //スペクテイターモード
    public boolean isSpectator() {
        return false;
    }

    @Override //クリエイティブモード
    public boolean isCreative() {
        return false;
    }
}

ここで問題なのが GameProfile 引数です。ここにはゲームプロファイルすなわち固有データを入れなければいけないかもしれません。あと、PlayerEntity を継承すると、なぜか entity/render/RenderHumanUnit.javaextends RenderLiving<HumanUnit> でエラーが発生します。

The type HumanUnit is not a valid substitute for the bounded parameter <T extends EntityLiving> of the type RenderLiving<T>

RenderLiving の型には一致しないみたいです。 EntityPlayerEntityLiving から継承されていないからかもしれません。そこで、もしやと思って RenderPlayer があるのかと思って入力してみたら、ありました。

3. RenderPlayer を継承してみる

entity/render/RenderHumanUnit.java にて RenderPlayer を継承してみましたが、すごく赤線(エラー)が出てしまいました。メソッドの引数に何を入れたらよいのか分からないので参照してみます。

前回までは RenderLiving のコンストラクタに色々代入していました。こんな感じでしたね。

public RenderLiving(RenderManager rendermanagerIn, ModelBase modelbaseIn, float shadowsizeIn)
{
    super(rendermanagerIn, modelbaseIn, shadowsizeIn);
}

今回継承した RenderPlayer はこんな感じです。

public RenderPlayer(RenderManager renderManager)
{
    this(renderManager, false);
}

どうやら RenderManager だけを代入すれば描画してくれそうですね。とりあえず RenderHumanUnit.java を書きかえてみます。

public class RenderHumanUnit extends RenderPlayer
{
    public static final ResourceLocation TEXTURES = new ResourceLocation(TakunologyMod.MODID + ":textures/entity/humanunit_1.png");

    public RenderHumanUnit(RenderManager manager)
    {
        super(manager);
    }
}

そして実行しようとしたら...

f:id:takunology:20200313092844p:plain

今度はイベントハンドラで型が合わないといわれてしまいました。

4. 試行錯誤の結果

色々やってみて気づいたのですが、プレイヤーのテクスチャ(スキン)はマインクラフトのサーバ上にアップロードする仕組みになってから複雑になっています。サーバ上のプレイヤープロファイルとそのスキンが紐づけられており、それを適切に処理するためのレンダラークラスが書かれています。

ということで、EntityPlayer を継承してスキンを自由に変更するのは技術的に難しいという判断をしました。おそらくレンダラー関係をいじろうとすると大量のクラス内での変更が必要かと...。

ちょっと継承する Entity を村人ベースにすべきか検討します。