Minecraftの座標や方角について確認した

# 背景

「おとうさんすごい」と言わせたくて、手探りでマインクラフトのMOD作りを始めてみたのですが、座標関係が頭に入りません。ブロックの配置を指示するFacingプロパティと、座標のXYZと、座標のFacingの話がごっちゃになってきたので一度落ち着いて確認してみました。

# 環境

環境作成についてはいろいろなところで紹介されていますので割愛しますが、下記バージョンを利用しています。

- macOS High Sierra(version 10.13.5)
- IntelliJ IDEA 2018.1.4(Community Edition)
- java version 1.8.0_111
- forge-1.12.2-14.23.4.2703-mdk

# 座標の定義

公式によると座標の定義は下記になります。
これについて、コードを書いて確認したいと思います。

|座標|方角|
|:---|:---|
|+x|東|
|-x|西|
|+y|上|
|-y|下|
|+z|南|
|-z|北|

(参考 [Coordinates - Official Minecraft Wiki](https://minecraft.gamepedia.com/Coordinates))

# デバッグ画面の軸と座標の対応を確認する

デバッグ画面の`Facing`が示す方角を正しいとして、自身のx+1(東)に丸石ブロック、z+1(南)に氷ブロックを置いて軸を確認してみます。

__コード実行時__

実行すると、赤い軸の方向に丸石ブロック(東想定)、青い軸の方向に氷ブロック(南想定)が配置されました。
![2018-07-03_06.35.06.png](https://qiita-image-store.s3.amazonaws.com/0/265837/2130ac44-06b9-a049-6f84-614e5bb2f284.png)

__`Facing`との比較　南向き__

デバッグ画面上の`Facing`が `south` の方向を向くと、ｚ＋１(南)に置いた氷ブロックが目の前にあり、`south(南）`は`+zの方向`であり、`青い軸`だということがわかります。
![2018-07-03_06.56.16.png](https://qiita-image-store.s3.amazonaws.com/0/265837/17d5ac3d-4c1f-06fa-8d38-df9c28aff8e1.png)

__`Facing`との比較　東向き__

デバッグ画面上の`Facing`が `east` の方向を向くと、x＋１(東)に置いた丸石ブロックが目の前にあり、`east(東）`は、`+xの方向`であり、`赤い軸`だということがわかります。

![2018-07-03_06.56.30.png](https://qiita-image-store.s3.amazonaws.com/0/265837/0f37d887-7ee8-c62c-2dc8-2825429f5720.png)


__まとめると、デバッグ画面上の軸と座標は以下のように対応することがわかりました。__

|座標|方角|軸|
|---|---|---|
|+x|東|赤|
|-x|西||
|+y|上|緑|
|-y|下||
|+z|南|青|
|-z|北||

## 確認コード

```java:ExampleMod.java
package com.example.examplemod;

import net.minecraft.init.Blocks;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import org.apache.logging.log4j.Logger;

@Mod(modid = ExampleMod.MODID, name = ExampleMod.NAME, version = ExampleMod.VERSION)
public class ExampleMod
{
    public static final String MODID = "examplemod";
    public static final String NAME = "Example Mod";
    public static final String VERSION = "1.0";

    private static Logger logger;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event)
    {
        logger = event.getModLog();
    }

    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        // some example code
        logger.info("DIRT BLOCK >> {}", Blocks.DIRT.getRegistryName());
    }

    @EventHandler
    public void start(FMLServerStartingEvent event){
        event.registerServerCommand(new ExampleCommand());
        logger.info("RegisterCommand");
    }

}

```

```java:ExampleCommand.java
package com.example.examplemod;

import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;

public class ExampleCommand extends CommandBase {

    @Override
    public String getName() {

        return "ex1";
    }

    @Override
    public String getUsage(ICommandSender sender) {
        return "usage";
    }

    @Override
    public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
        Entity player = sender.getCommandSenderEntity();

        //南(Z軸)
        BlockPos south = new BlockPos(player.posX, player.posY, player.posZ + 1);

        //東(X軸)
        BlockPos east = new BlockPos(player.posX + 1, player.posY, player.posZ);

        //南に氷を配置
        server.getEntityWorld().setBlockState(south, Blocks.ICE.getDefaultState());
        //東に丸石を配置
        server.getEntityWorld().setBlockState(east, Blocks.COBBLESTONE.getDefaultState());
    }

}
```

# ブロックのFacingプロパティを確認する

ブロックにも、Facingプロパティを持つものがあります。
トーチ、ボタンについて確認してみました。

## トーチブロック

地面にも置けますが、壁にもくっつけられるタイプのブロックです。
`Facing=south`と指定して配置してみます。

__コード実行結果__

南側のブロックにトーチが配置されると思いきや、逆の北側のブロックに配置される結果となりました。
![2018-07-03_17.38.06.png](https://qiita-image-store.s3.amazonaws.com/0/265837/f8a09a9f-fe58-56d1-1525-57964c7033f8.png)

公式ドキュメントによるとトーチのFacingは下記の定義になるようです。トーチの先端が南を向くように配置されるようです。

*私が混乱したきっかけはこれでした。*

|Name|Value|Description|
|----|-----|-----|
|facing|up<br>north<br>east<br>south<br>west|The direction the top of the torch is facing.|

(引用元 [Block States - Official Minecraft Wiki](https://minecraft.gamepedia.com/Block_states))

### 確認コード(抜粋)

```java
    @Override
    public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
        Entity player = sender.getCommandSenderEntity();

        BlockPos south = new BlockPos(player.posX, player.posY, player.posZ + 1);
        BlockPos north = new BlockPos(player.posX, player.posY, player.posZ - 1);
        BlockPos east = new BlockPos(player.posX + 1, player.posY, player.posZ);
        BlockPos west = new BlockPos(player.posX - 1, player.posY, player.posZ);
        BlockPos center = new BlockPos(player.posX, player.posY, player.posZ);

        //丸石を4方向に配置
        server.getEntityWorld().setBlockState(south, Blocks.COBBLESTONE.getDefaultState());
        server.getEntityWorld().setBlockState(north, Blocks.COBBLESTONE.getDefaultState());
        server.getEntityWorld().setBlockState(east, Blocks.COBBLESTONE.getDefaultState());
        server.getEntityWorld().setBlockState(west, Blocks.COBBLESTONE.getDefaultState());

        //丸石の南面にトーチを配置
        server.getEntityWorld().setBlockState(center, Blocks.TORCH.getBlockState().getBaseState().withProperty(BlockTorch.FACING, EnumFacing.SOUTH));
    }
```
## ボタンブロック

ボタンは、上下も含めた全方向にくっつけて配置できるブロックです。

__コード実行結果__

`Facing=south`で配置したボタンは、北側の面に配置されています。

![2018-07-03_23.04.29.png](https://qiita-image-store.s3.amazonaws.com/0/265837/81d5c74e-c8d3-e5ea-6c2a-ec557baa112f.png)

公式では、下記のように定義されており、やはり`Facing=south`で南に配置すると北側のブロックに配置されるようで、仕様通りの動作です。

|Name|Value|Description|
|:--|:--|:--|
|facing|north<br>west<br>south<br>east<br>up<br>down|The direction it's facing.<br>Opposite to the direction the player is facing if placed on the side of a block.|

(引用元 [Block States - Official Minecraft Wiki](https://minecraft.gamepedia.com/Block_states))

# ついでにブロックのaxisプロパティについても確認

ブロックによっては、axisというXYZを表すプロパティもありますので、そちらも確認してみました。

## 丸太ブロック

南側にZ軸向き、東側にX軸向きで配置しました。

__コード実行結果__

年輪が指定したaxis方向へ向きました。
トーチやボタンと違って、想定どおりの配置となっています。

![2018-07-03_23.29.41.png](https://qiita-image-store.s3.amazonaws.com/0/265837/6414a205-eac8-2f51-266d-ec4bee412dbc.png)

### 確認コード(抜粋)
```java
BlockPos south = new BlockPos(player.posX, player.posY, player.posZ + 1);
BlockPos east = new BlockPos(player.posX + 1, player.posY, player.posZ);

server.getEntityWorld().setBlockState(south, Blocks.LOG.getBlockState().getBaseState().withProperty(BlockLog.LOG_AXIS, BlockLog.EnumAxis.Z));
server.getEntityWorld().setBlockState(east, Blocks.LOG.getBlockState().getBaseState().withProperty(BlockLog.LOG_AXIS, BlockLog.EnumAxis.X));
```

# まとめ

- 方角はZ方向が南、X方向が東
- デバッグ画面の青軸は南、赤軸は東
- ブロックのプロパティの挙動は、ブロックによるのでドキュメント要確認

青南Z、赤東X、よい語呂がおもいつかない・・・。

方角と座標については無論ドキュメント通りでしたが、実際に試すことで理解できたかなと思います。
ドキュメントの見方もわかってきたので、MOD作りに励もうと思います。