Minecraft 1.8.9 Forge の Mod 開発で Block を追加してみた

# はじめに

この記事は、Minecraft の Mod開発を勉強し始めたおっさんの備忘録です。まだまだ右も左もわからないので間違いだらけかもしれませんが、少しでも誰かの役に立てたら幸いです。

**2016/3/6 更新しました！**

もっとシンプルにやる方法があるので、[こちらを参考にしてみてください](https://github.com/Kurosawa/PerpetualCraft)

本記事では、ブロックが複数の「状態」を持つパターンでのコーディングです。「複数の状態」とは染料などで色を変えられるなどのことを示します。

しかし、単純なブロックの追加ならばコーディング量はもっと減ります。本記事の最後にサンプルを掲載しますので参考にしてみてください。


環境構築は[こちら](http://qiita.com/Chrowa3/items/e3a4d1533f2f509d8f0a)から（Forge 1.9での環境構築ですが、1.8.9と大差ないです）

## 前提

* Mac OS X Yosemite
* Java 1.8.0_25
* Eclipse Mars.1 Release (4.5.1)

## 参考

* [Minecraft Modding Wiki](http://minecraftjp.info/modding/index.php/1.8%E3%81%AEB3D%E3%83%A2%E3%83%87%E3%83%AB%E5%88%A9%E7%94%A8%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%BF%BD%E5%8A%A0)
* ComputerCraft 1.78 のリソース

Modの開発環境構築は → [こっちを参考にどうぞ](http://qiita.com/Chrowa3/items/e3a4d1533f2f509d8f0a)
Eclipse の導入は → [こっちを参考にどうぞ](http://qiita.com/Chrowa3/items/bdd6bb7df02b974ef4b5)

Mod 開発の手始めとして「ブロックの追加」をしてみました。日本語での情報が少なかったので、Minecraft Modding Wiki のソースを参考にブロックの追加をしてみました。

![スクリーンショット 2016-02-28 14.24.05.png](https://qiita-image-store.s3.amazonaws.com/0/9988/29215745-af94-8079-ffe9-cff1c9dccc9c.png)

このブロックは光っているだけの単純なブロックです。テクスチャーは Photoshop で作りました。

ソースはほぼコピペですが学ぶことは多いで、これを基準に学んでいこうと思います。

## 用意したファイル

用意したのは以下のファイルです。assets 配下の以下のものは全てディレクトリで、Eclipse上で追加していきました。

* assets/chrowa3mod/blockstates
* assets/chrowa3mod/models/block
* assets/chrowa3mod/models/item
* assets/chrowa3mod/textures/blocks

![スクリーンショット 2016-02-29 21.30.34.png](https://qiita-image-store.s3.amazonaws.com/0/9988/780e99dc-158d-106e-18ee-b3e4cd48c4ee.png)


*※Chrowa3Apple.java や chrowa3apple.json、chrowa3Item.java、chrowa3item.json は気にしないでください*

## javaのソース

### Modのイニシャライズ
ModのIDや、名前、バージョン、前提Mod、対応させるMinecraftのバージョンなどを設定しているようです。

また、preInitでは、ブロックを追加するための登録を GameRegistry.registerBlock() で行っています。

読み込むべきリソースがある場合は、`ModelLoader.setCustomModelResourceLocation` で指定するようです。

```java:Chrowa3Sample.java
package in.webya.Chrowa3Sample;

import net.minecraft.block.Block;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;

@Mod(modid = Chrowa3Sample.MOD_ID, 
name = Chrowa3Sample.MOD_NAME, 
version = Chrowa3Sample.MOD_VERSION, 
dependencies = Chrowa3Sample.MOD_DEPENDENCIES,
acceptedMinecraftVersions = Chrowa3Sample.MOD_ACCEPTED_MC_VERSIONS,
useMetadata = true)
public class Chrowa3Sample
{
    public static final String MOD_ID = "chrowa3mod";
    public static final String MOD_NAME = "Chrowa3Mod";
    public static final String MOD_VERSION = "0.0.1";
    public static final String MOD_DEPENDENCIES = "required-after:Forge@[1.8-11.14.0.1239,)";
    public static final String MOD_ACCEPTED_MC_VERSIONS = "[1.8,1.8.9]";
    public static Block chrowa3block;
    
    
    @EventHandler
    public void preInit(FMLPreInitializationEvent event)
    {
        chrowa3block  = new Chrowa3Block();
        GameRegistry.registerBlock(chrowa3block, Chrowa3ItemBlock.class, "chrowa3block");
 
        if (event.getSide().isClient())
        {
            ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(chrowa3block), 0, new ModelResourceLocation(MOD_ID + ":" + "chrowa3block", "inventory"));
        }
    }
}

```


### ブロックの設定(2016/2/29更新)

ブロックを定義するクラスでは、Block クラスを extends します。親クラスのコンストラクタへは Material クラスの定数を渡しています。これで設定されるのは `new Material(MapColor.stoneColor)` の色と `setRequiresTool` による「回収不可能」だという設定になるようです。選択した素材でそのブロックの特性が変わるので、 Material クラスの確認が必要になるでしょう。

あとは諸々の設定を行い、コンストラクタの最後では、初期状態を設定します。初期状態を設定するにあたりこのファイルの先頭で行っている、列挙型による json リソースとのひも付けです。ここでは一つだけの設定なので列挙型で行う必要があるのかっていうとアレですが、こうしておけば追加・変更に即座に対応できます。


```java:Chrowa3Block.java


package in.webya.Chrowa3Sample;

import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.util.IStringSerializable;


public class Chrowa3Block extends Block
{

    public enum EnumType implements IStringSerializable
    {

        CHROWA3(0, "chrowa3");

        private int ID;
        private String name;

        private EnumType(int ID, String name)
        {
            this.ID = ID;
            this.name = name;
        }


        @Override
        public String getName()
        {
            return name;
        }

        public int getID()
        {
            return ID;
        }
    }

    public static final PropertyEnum TYPE = PropertyEnum.create("type", Chrowa3Block.EnumType.class);

    public Chrowa3Block()
    {
        super(Material.rock);
        setCreativeTab(CreativeTabs.tabDecorations);
        setUnlocalizedName("Chrowa3");
        setHardness(1.5F);
        setResistance(1.0F);
        setStepSound(Block.soundTypeStone);
        disableStats();
        setLightOpacity(1);
        setLightLevel(1.0F);
        this.setDefaultState(this.blockState.getBaseState().withProperty(TYPE, EnumType.CHROWA3));
    }

    @Override
    public IBlockState getStateFromMeta(int meta)
    {
        return getDefaultState().withProperty(TYPE, EnumType.CHROWA3);
    }

    @Override
    public int getMetaFromState(IBlockState state)
    {
        EnumType type = (EnumType) state.getValue(TYPE);
        return type.getID();
    }

    @Override
    protected BlockState createBlockState()
    {
        return new BlockState(this, new IProperty[] { TYPE });
    }
}

```

`getStateFromMeta()` や `getMetaFromState()` はブロック設置時の状態や、ドロップ時の状態を設定しているようです。

`createBlockState()` は ブロックの状態を生成するメソッドのようです。

大体が憶測なので、分かり次第更新します。


### アイテムの設定

コンストラクタでは、ItemBlock のコンストラクタを呼んでいるだけです。

```java:Chrowa3ItemBlock.java
package in.webya.Chrowa3Sample;

import net.minecraft.block.Block;
import net.minecraft.item.ItemBlock;

public class Chrowa3ItemBlock extends ItemBlock
{
    public Chrowa3ItemBlock(Block block)
    {
        super(block);
    }
}
```


## JSONによるもろもろの設定

### 各モデルとのひも付けを行っている assets/chrowa3mod/blockstates

最小構成にと meta=1 の行を消してみたらエラー吐いてた

```json:chrowa3block.json
{
    "variants": {
        "type=chrowa3":  { "model": "chrowa3mod:chrowa3block" }
    }
}
```

### Block の設定周りを行う assets/chrowa3mod/models/block 配下

```json:chrowa3block.json
{
    "parent": "block/cube_all",
    "textures": {
        "all": "chrowa3mod:blocks/face"
    }
}
```

### Item の設定周りを行う assets/chrowa3mod/models/item 配下

```json:chrowa3block.json
{
    "parent": "chrowa3mod:block/chrowa3block",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}
```

設定内容は見ての通りです。




## まとめ

ブロックの追加に関しては、「プログラミングをする」という感覚は無くその殆どが「設定」に尽きるみたいです。きっとレシピの追加などもそういうことなんでしょうけど、いかんせん情報が少ない。本家のサイト（英語）を頑張って読むのが一番いいのかな。ってことで生暖かい目で見守ってくださいな。





## 複数の状態を持たないような単純なブロック

### Block Classを継承したクラス

```java

package in.webya.PerpetualCraft;

import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;

public class CharcoalBlock extends Block {

	public CharcoalBlock() {
		super(Material.rock);
		setCreativeTab(CreativeTabs.tabBlock);
		setUnlocalizedName("CharcoalBlock");
		setRegistryName("CharcoalBlock");
		setHardness(1.5F);
		setResistance(1.0F);
		setStepSound(Block.soundTypeStone);
		disableStats();
		setLightOpacity(1);
	}
}

```


### ItemClass を継承したクラス

```java

package in.webya.PerpetualCraft;

import net.minecraft.block.Block;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;

public class CharcoalItemBlock extends ItemBlock {
	public CharcoalItemBlock(Block block) {
		super(block);
		setUnlocalizedName("CharcoalItemBlock");
		setRegistryName("CharcoalItemBlock");
	}
}

```

### メインのクラス

```java

// member
public static Block charcoalBlock;

// preInit() 内
charcoalBlock = new CharcoalBlock();
GameRegistry.registerBlock(charcoalBlock, "charcoalblock");
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(charcoalBlock), 0, new ModelResourceLocation(MOD_ID + ":" + "charcoalblock", "inventory"));
```

## asset で用意するリソース

### BlockState

```json:charcoalblock.json
{
    "variants": {
        "normal": { "model": "perpetualcraft:charcoalblock" }
    }
}
```

### models/block

```json:charcoalblock.json
{
    "parent": "block/cube_all",
    "textures": {
        "all": "perpetualcraft:blocks/charcoalblock"
    }
}
```

### models/item

```json:charcoalblock.json
{
    "parent": "perpetualcraft:block/charcoalblock",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}
```

### lang

```en_US.lang
tile.CharcoalBlock.name=Charcoal Block
```

```ja_JP.lang
tile.CharcoalBlock.name=木炭ブロック
```

このコードは [こちら](https://github.com/Kurosawa/PerpetualCraft) でも詳しく見ることができます。