今回は基本的なブロックの追加と登録を行います。

マイクラにおけるブロックは様々なものがあり、大変奥深いですが今回はOreとかCube等の

普通の立方体のブロックです。

Blockについては↓を一読するのがお勧めではあります

ForgeDocumentationへ

がForgeDocumentationの内容+αのメモを載せておきます。

難しい内容もあってさっぱりわからんのも多々ありますが(-_-;)

Blockはmod制作の最初にやるには割と難易度が高い(;´Д`)

 

特別な機能を持たないベーシックなブロックの場合はカスタムクラスは必要なくBlockクラスを

インスタンス化してセッターを呼び出すだけで様々なブロックの作成が可能である。

setHardnessはブロックを解除するのにかかる時間を制御(硬度)。引数に任意の値を入れる。

石が1.5F土が0.5F flortなので数字の語尾にFをつける。設定しないと一撃で壊れる。

setResistanceはブロックの耐爆性を制御。硬度とは別だが抵抗がこの値よりも低い場合は

setHardnessは抵抗を硬度値の5倍に設定する。引数で渡した値(flot)に3.0Fを乗算したものが

返される。設定した抵抗値が硬度値×5.0Fより小さい場合はsetHardnessメソッドの式によって抵抗値が硬度値×5.0Fの数値となる。

setSoundTypeはブロックがパンチ、破損、配置されたときにブロックが発する音を制御。

SoundType引数が必要で詳細はサウンドページを参照。SoundTypeというクラスがあるので

既存のサウンドを指定する場合はここから選ぶ。Blockクラスを使用してインスタンス化する場合はこのメソッドがprotectedになっているので直接は呼びだせない。

BlockクラスのコンストラクタでサウンドがSTONEにされている。

サウンドを変えたいときは自分でクラスを作成してBlockクラスを継承させてオーバライドした

クラスでインスタンス化する。

setLightLevelはブロックの発光を制御。このメソッドは0~15ではなく0~1の値を取る。

この値を計算するにはブロックが放出する光レベルを取得し16で除算する。

例えばLV5の光を放出するブロックはこのメソッドに5/16Fを渡す必要がある。

グロウストーンと同じように光らすには1.0Fを引数として渡す。16/16Fでもいい。

引数で渡す数値に15.0Fをかけたものを発光レベルとして返している。(intがキャストされているので小数点以下は切り捨てられる。)

setLightOpacityはこのブロックを通過する光が暗くなる量を制御。この値は0~15までの整数。

3に設定するとこのタイプのブロックを通過するたびにライトが3レベル下がる。

setUnlocalizedName-ブロックのローカライズされていない名前を設定します。 この名前の前には「タイル」が付きます。 ローカリゼーションのために「.name」が追加されています。 たとえば、setUnlocalizedName( "foo")を使用すると、ブロックの実際のローカリゼーションキーは「tile.foo.name」になります。 より高度なローカリゼーション制御には、カスタムアイテムが必要になります。ブロックの名前をString型で付ける必須項目。

setCreativeTab-このブロックがどのクリエイティブタブに分類されるかを制御します。 ブロックをクリエイティブメニューに表示する必要がある場合は、これを呼び出す必要があります。 タブオプションは、CreativeTabsクラスにあります。必須ではない。水などクリエイティブタブにはないブロックもある。独自のクリエイティブタブを追加している場合はそこを指定することもできる。

これらのセッターと登録用の

 public final T setRegistryName(ResourceLocation name){ return setRegistryName(name.toString()); }
        public final T setRegistryName(String modID, String name){ return setRegistryName(modID + ":" + name); }

のどちらかを呼び出さないといけない。

setRegistryName(new ResourceLocation(MODID, "platinum_ore"));

カスタムクラスなしのBlockクラスを利用したインスタンス化でチェーンをつなぐ例

例: public static Block platinum_ore = new Block(Material.ROCK)
                    .setUnlocalizedName("platinum_ore")
                    .setCreativeTab(CreativeTabs.BUILDING_BLOCKS)
                    .setHardness(1.5F)
                    .setResistance(1.0F)

          .setLightOpacity(3)

                    .setLightLevel(1.0F)
                    .setRegistryName(new ResourceLocation(MODID, "platinum_ore"));

 

setBlockUnbreakbleはブロックを破壊できなくする。岩盤みたいに。

赤字のメソッドはチェーン可。

 

ItemToolの方も必要ですが

/**
     * Sets or removes the tool and level required to harvest this block.
     *
     * @param toolClass Class
     * @param level Harvest level:
     *     Wood:    0
     *     Stone:   1
     *     Iron:    2
     *     Diamond: 3
     *     Gold:    0
     */
    public void setHarvestLevel(String toolClass, int level)
    {
        java.util.Iterator<IBlockState> itr = getBlockState().getValidStates().iterator();
        while (itr.hasNext())
        {
            setHarvestLevel(toolClass, level, itr.next());
        }
    }

という収穫LVを設定するメソッドもあります。これはチェーンの中には入れられない。

チェーンする為の戻り値の型はBlockなので戻り値なしのメソッドはチェーンに入れられない。

単品での呼び出しはできます。

setHarvestLevel("pickaxe", 4);

toolClassというのもItemToolクラスで設定されているもので

基本は つるはし シャベル 斧 の3つがそれにあたります。

なので引数には pickaxeかshovelかaxeをいれます。

LVについてはコメントの通りダイヤモンドが3鉄が2石が1木と金が0。

マイクラでは黒曜石がダイヤモンドのつるはし以外では収穫できないように

Toolのクラスで設定されています。他の道具だと黒曜石をドロップしません。

破壊はどのつるはしでも壊せますが・・・。同じようにsetHarvestLevel("pickaxe", 3);

とすればダイヤモンドのつるはしだけ収穫できるブロックが出来上がります。

lvを2にすれば鉄のつるはしとダイヤモンドつるはしだけで収穫できるブロックになります。

LV4以上にするには新しいToolクラスを作成する必用があります。

Toolクラスのメソッドの内容を書き換えてブロックの収穫LV==4 なら~と

それ以下なら~という風に設定すればオリジナルのツールでしか収穫できないブロックが

できます。

 

Blockクラスのコンストラクタは

大抵は下の方のコンストラクタを使用すると思われます。

下のコンストラクタで上のコンストラクタを呼んでいるのでオーバライドしない限りは

上のコンストラクタのフィールドでblockのステータスが設定される。

共通のもので必要な要素は予めコンストラクタに入っているから

最低限名前やMaterialを入れればブロックの作成が出来るようになっているみたいですね。

ここで音が石になっているのでカスタムクラスで音を変えない限りは石で固定です(;´Д`)

鉱石とかそういったものを追加する分にはBlockクラスをインスタンス化して

セッターで名前や硬度などを設定すればいいけど土やガラス素材や金属などのブロックを

作成するならBlockクラスを継承した新しいクラスが必要になります。

音を気にしないなら、普通の立方体のブロックなら何でも作れるのは作れます。

 

Material はMaterialクラスをみればわかると思いますが新しいMaterialも設定できます。

燃えない木材とかできるわけですが大抵はMaterialクラスの中から選ぶと思います。

public static final Material WOOD = (new Material(MapColor.WOOD)).setBurning();
public static final Material ROCK = (new Material(MapColor.STONE)).setRequiresTool();

後ろの.~のメソッドを付けたり消したりして新しいMaterialを宣言・・・

インスタンス化すればそれも使用可能に。

他のメソッドなどはMaterialクラスを見てください(-_-;)

まあ・・・燃えない木材についてはテクスチャだけ木材のROOKでもいいわけなので

Materialクラス内にない物をどうしても作りたいときだけでしょうかね。

木材が燃えるのは後ろの.setBurningメソッドのせいですね。雷が落ちてよく村の屋根が

大惨事になりますよね・・・( ノД`)シクシク…。暖炉の失敗もやりました・・・ちょっとコンビニへ

言っている間にせっかく建てた家が燃えてましたね・・・。

他にも専用ツールでないと掘れないとかそういったことが設定できます。

 

インスタンス化したブロックは登録する必要があります。

ワールド内に生成または設置するブロックとインベントリや手に持っている状態のブロックは

異なるものでワールド内のブロックはIBlockStateで表され、その動作はBlockのインスタンスで定義されて、インベントリ内のアイテムはItemStackであり、Itemによって制御されます。

BlockとItemの異なる世界の間の架け橋として、ItemBlockクラスが存在します。

ItemBlockは、それが表すブロックへの参照を保持するフィールドブロックを持つItemのサブクラスです。ItemBlockは、右クリックでブロックを配置する方法など、「ブロック」の動作の一部をアイテムとして定義します。ItemBlockなしでブロックを持つことは可能です。(水や溶岩など)

ブロックを登録すると、ブロックのみが登録されます。ブロックに自動的にItemBlockが含まれることはありません。

ブロックの基本的なItemBlockを作成するには、new ItemBlock(block).setRegistryName(block.getRegistryName())を使用する必要があります。

ローカライズされていない名前は、ブロックの名前と同じです。 ItemBlockのカスタムサブクラスも使用できます。ItemBlockがブロックに登録されると、Item.getItemFromBlockを使用してブロックを取得できます。ブロックのItemBlockがない場合、Item.getItemFromBlockはnullを返すため、使用しているブロックのItemBlockがあるかどうかわからない場合は、nullを確認してください。

 

ここまで一旦ブロックの追加と登録をやります。以前Blockクラスをそのままインスタンス化

しての追加と登録をやりましたのでそれは省略します。

block用にフォルダを作成してその中にブロック関係のクラスを入れていきます。

インターフェースを2つ作成します。

クラスの名前やメソッド名は自分が分かりやすいもので。

Ore用のクラスを作成Blockクラス(minecraftの)を継承。先ほど作った2つのインタフェース

も継承します。スパークラスのコンストラクタの呼び出しとインタフェースのメソッドの実装を

促されるのでそれらを行います。

コンストラクタの内容は最低限必要なものだけであとは登録時にセッターを呼び出して

つなげればokです。硬さとか鉱石によって違う設定にしたいですしね。

この辺はお好みでクリエイティブタブも個々で入れる場所を変えたいなどあれば

登録時のセッターの呼び出しで行うならここでは設定しなくてもいいです。

クラスが出来たら次は登録用のクラスを作成します。

eventメソッドを使用した登録のやり方です。

Itemの登録はしない場合はインターフェースのIBlockクラスを継承しないクラスを作成して

インスタンス化して登録すればいいと思います。

これだけではどこからもお呼ばれされないのでItemの時と同じように

CommonProxyクラスのpreInitで呼び出します。

さらにeventのアレもしないとeventが起こらないので

MODIDなどを登録したクラスのpreInitで赤枠の記述も必要です。

引数はインスタンスを入れます。eventの記述をしたクラスのです。

ここまで整えたら追加がとても楽になります。

1個か2個しかブロック追加しないよという方は以前やった記事の方で十分かと思います。

後はJsonファイル3つとpngファイルlangファイルなどを整えます。

(この辺は以前にやったので省略します)

eventメソッドではないやり方では↑みたいになります。(いつものやつですね)

Item登録しない場合はインターフェースのIBlockを継承させないクラスを作成して

ifで分岐させます。instanceofの便利さよ(*´Д`)

Blockクラスを継承してブロック作成の素になるクラスを作成。

変えたい箇所だけオーバーライド。

setSoundTypeはメソッドをオーバーライドしてpublicにした(´・ω・`)

コンストラクタの引数にいれてBlockBase(Material materialIn, String name,SoundType sound)

にしてもいいですがサウンドを変えない場合は面倒なので(-_-;)

後はインスタンス化するときに後ろに付け加えればOK

収穫LVは.で繋げられないので普通に インスタンスの変数名.setHarvestLevel(引数);

と記述します。繋げられないだけでちゃんとフィールドの設定は出来ます。

硬度などはそれぞれお好みで。

testという名前のブロックは実験用のものです(;´Д`)

test5はアイテム登録はしていないブロックです。

でもちゃんとブロックとして存在しているようなので登録はちゃんとうまくいているようです。

ちゃんと他のmodでも使えると一安心ですね。

test5はクリエイティブタブには入っていないです。

/giveコマンドでもtest5は手に入らないです。

水と同じですね。空気ブロックは/giveコマンドでゲットできるけど何もないw

mod制作をしていると色々仕組がわかって面白いですね。

長くなったので続きはまた次回で(`・ω・´)