[Minecraft] マイクラでPythonスクリプトを動かしてみよう!(Minescriptを使った巨大トンネル作成編)

Minecraft

Minescript(Minecraft用のPythonプログラム実行Mod)を利用してPythonスクリプトを動かしてみます。
今回は山脈に巨大なトンネルを作ります。

Python実行環境準備

まずはこちらを参考に、Minecraft上でPythonスクリプトを実行できる環境を用意します。

スクリプト作成

Minecraft上で実行するPythonスクリプトを作成していきます。

my_tunnel.pyファイル作成

ここでは「my_tunnel.py」というファイル名で作成します。
場所は%appdata%\.minecraft\minescriptフォルダに保存します。

りお
りお

保存するフォルダを間違えると、スクリプトを実行できないのでご注意ください。

スクリプト全体

今回のソースコードは以下です。
コピー&ペーストで大丈夫ですので、まずはこちらをmy_tunnel.pyに貼り付けて保存します。

りお
りお

ソースコードの内容については以下で解説しますが、
まずは実行してみてどんな動きになるかを見てもらった方が分かりやすいと思います。

import minescript

DISTANCE = 3000
SHAPE = [[0,0,0,0,0,1,1,1,0,0,0,0,0],
         [0,0,0,1,1,1,1,1,1,1,0,0,0],
         [0,0,1,1,1,1,1,1,1,1,1,0,0],
         [0,0,1,1,1,1,1,1,1,1,1,0,0],
         [0,1,1,1,1,1,1,1,1,1,1,1,0],
         [0,1,1,1,1,1,1,1,1,1,1,1,0],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1]]

H = len(SHAPE)
W = len(SHAPE[0])

NORTH = 1
EAST  = 2
SOUTH = 3
WEST  = 4

def get_direction(yaw):
    y = int(yaw) % 360
    if y < 45 or y >= 315:
        return SOUTH
    elif y >= 45 and y < 135:
        return WEST
    elif y >= 135 and y < 225:
        return NORTH
    elif y >= 225 and y < 315:
        return EAST

if __name__ == '__main__':
    (px, py, pz) = minescript.player_position()
    (yaw, pitch) = minescript.player_orientation()
    facing = get_direction(int(yaw))

    blockpacker = minescript.BlockPacker()
    for d in range(DISTANCE):
        for row in range(len(SHAPE)):
            for col in range(len(SHAPE[row])):
                if SHAPE[row][col] == 1:
                    if facing == NORTH:
                        blockpacker.setblock((int(px) + col - int(W/2), int(py) - row + H - 1, int(pz) - d - 1), "air")
                    elif facing == EAST:
                        blockpacker.setblock((int(px) + d + 1, int(py) - row + H - 1, int(pz) + col - int(W/2)), "air")
                    elif facing == SOUTH:
                        blockpacker.setblock((int(px) + col - int(W/2), int(py) - row + H -1, int(pz) + d + 1), "air")
                    elif facing == WEST:
                        blockpacker.setblock((int(px) - d - 1, int(py) - row + H - 1, int(pz) + col - int(W/2)), "air")

    blockpacker.pack().write_world()

スクリプト解説

簡単にスクリプトを解説します。

DISTANCE = 3000

DISTANCEはトンネルを掘る距離を定義しています。
ここでは3000ブロックを指定していますが、必要に応じて変更して大丈夫です。

SHAPE = [[0,0,0,0,0,1,1,1,0,0,0,0,0],
         [0,0,0,1,1,1,1,1,1,1,0,0,0],
         [0,0,1,1,1,1,1,1,1,1,1,0,0],
         [0,0,1,1,1,1,1,1,1,1,1,0,0],
         [0,1,1,1,1,1,1,1,1,1,1,1,0],
         [0,1,1,1,1,1,1,1,1,1,1,1,0],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1],
         [1,1,1,1,1,1,1,1,1,1,1,1,1]]

H = len(SHAPE)
W = len(SHAPE[0])

SHAPEはトンネルの形を定義しています。
配列で定義するようにしていて、0の部分は何もしない(掘らない)で、1の部分でブロックを掘る(正確にはairブロックで埋める)ような処理にしています。
こちらも、もっと大きいトンネルを作りたい場合は配列を増やしてもらえたらいいですし、形も自由に変更できます。
HWはトンネルの形の高さ(H)と幅(W)として定義しています。

NORTH = 1
EAST  = 2
SOUTH = 3
WEST  = 4

def get_direction(yaw):
    y = int(yaw) % 360
    if y < 45 or y >= 315:
        return SOUTH
    elif y >= 45 and y < 135:
        return WEST
    elif y >= 135 and y < 225:
        return NORTH
    elif y >= 225 and y < 315:
        return EAST

get_direction関数は、トンネルを掘る方向を決めています。
プレイヤーが向いている方角にトンネルを掘るためで、このプログラムでは単純に東西南北に直線的に掘ることにしか対応していません。
(プレイヤーの向いている方角に斜めに掘ることもできると思いますが、プログラムは複雑になります)

    (px, py, pz) = minescript.player_position()
    (yaw, pitch) = minescript.player_orientation()
    facing = get_direction(int(yaw))

minescript.player_position関数で、プレイヤーの位置を取得します。
minescript.player_orientation関数で、プレイヤーが向いてる方角(yaw)と水平に対して向いている角度(上向き or 下向き)(pitch)を取得します。
get_direction関数を呼び出して、東西南北のどの方向にトンネルを掘るかを決めています。

    blockpacker = minescript.BlockPacker()
    for d in range(DISTANCE):
        for row in range(len(SHAPE)):
            for col in range(len(SHAPE[row])):

3重ループでトンネルの形をトンネルを掘る距離分を繰り返し実行します。

                if SHAPE[row][col] == 1:
                    if facing == NORTH:
                        blockpacker.setblock((int(px) + col - int(W/2), int(py) - row + H - 1, int(pz) - d - 1), "air")

1の場合にブロックを掘る(airブロックで埋める)処理とするため、airブロックを指定された場所のブロックに埋めています。
airブロックを他のブロックに埋めて実行することもできます。
方角によって、x軸とz軸を計算しないといけないため、東西南北の4つの場合分けが必要になっています。

ブロックID一覧はこちらでまとめてくれていますので参考に。

【マイクラ1.21対応】ブロックID一覧!部分一致検索対応【JavaEdition】
マインクラフトJava Edition1.21における、ブロッグID・アイテムIDをまとめています。 giveコマンド等でブロックID・アイテムIDが必要になるので、確認しましょう。 コピーして使えるgiveコマンド付きです。
    blockpacker.pack().write_world()

最後にairブロックで埋めた内容を反映することで、巨大なトンネルを作成することができます。

スクリプト実行

実際にMinecraftのワールド上でスクリプトを実行してみましょう。

ワールド上でスクリプトを実行

ワールドを開いて、以下のコマンドを実行します。

\my_tunnel

実行結果

正常に動作すると、山脈に巨大なトンネルが生成されます。

今回はx軸またはz軸方向にトンネルを掘ってみましたが、x軸方向に掘ることで巨大な穴を掘ることもできます。
奈落も一瞬で作ることができそうです。

コメント

タイトルとURLをコピーしました