JAVA版_shatter world limits_minescript_QGIS_GDAL

20250903 ★★★★★★★★★今までまでのまとめ★★★★★★★★★

参考までに

---<pythonで dir変更は>------------------------------------------
>>>import os
>>>print(os.getcwd())
---------------------------------------------------
ディレクトリの変更した
---------------------------------------------------------
>>>os.chdir('C:/Users/Yasushi/SynologyDrive/Minecraft')
-------------------------------------------------------

minecraft 1.19.3 に downversion

forge 1.19.3 installer download and install


shatteredworldlimits-0.2.0-512-forge-1.19.3.jar
minescript-mc1.19.3-forge-mod-3.2.jar

を探してきて入れた.
C:\Users\byf04\AppData\Roaming\.minecraft\modsに配置
これだと大丈夫(かも)

C:\Users\Yasushi\AppData\Roaming\.minecraft\minescript\config.txt を書きに書き換える
そうないと[Exited with error code 9009]

# Lines starting with "#" are ignored.

#python="%userprofile%\AppData\Local\Microsoft\WindowsApps\python3.exe"
python="C:\Python39\python.exe"

helloworld.pyなる下記のファィルを作り,C:\Users\Yasushi\AppData\Roaming\.minecraft\minescriptにおく
import minescript
minescript.echo("Hello world!")

で OK

 

Shattered World Lmits で 高度の制限を 1024 にして
minescript が動くようにした

 

QGIS(https://qgis.org/)からゲットした LTS 版をインストールしていたのだが
OSGeo4w をゲット
.....GDALをpythonから使う必要があるのだが(使わない方法もありそうだが),この導入が難しく,ここに入っている QGIS は GDAL とか使いやすそうだったのでやってみた
https://trac.osgeo.org/osgeo4w/wiki/OSGeo4W_jp
...死んでる
https://qgis.org/
ここにある
osgeo4w-setup.exe QGIS, GDAL 入れて install

quickDEM4JP なるプラグインをinstallした(LTS版にinstallしたものが再現されていた)
新規に入れるなら,QGISのプラグインマネージャから
これを使って 基盤情報地図から download した DEM ファィルを tiff にする

C:\Users\Yasushi\SynologyDrive\Minecraft において作業を進めてる


GDALを使った python script を作り
tiff ファイルは精度5mなので(補完して)精度1mにする

Pythonを使用して数値標高モデル(DEM)からMinecraftの地形を作成する
にあるコード(再掲)ではNG
------------------------------------------------
from osgeo import gdal


# 入力ファイルを開く
tiff = gdal.Open("kakuda.tiff", gdal.GA_ReadOnly)

# 変換パラメーターを設定
dst_size_x = 1
dst_size_y = 1

# 立方体補間(Cubic Convolution) で解像度を変更する
warp_options = gdal.WarpOptions(xRes=dst_size_x, yRes=dst_size_y, resampleAlg=gdal.GRIORA_Cubic)

# ラスターの変換を実行
dst = gdal.Warp("kakuda_1m.tiff", tiff, options=warp_options)

# ファイルをクローズ
src = None
dst = None
------------------------------------------------
CoPilot に教えてもらってFB
-------PrepKakudaCorrected(ByPyQGIS).py で保存 EPSGコードが新潟県でハードコードされているので注意---------------
from osgeo import gdal, osr

# 入力ファイルを開く
src_ds = gdal.Open("kakuda.tiff", gdal.GA_ReadOnly)

# UTM ゾーンの設定(例:新潟なら UTM Zone 54N)
srs = osr.SpatialReference()
srs.ImportFromEPSG(32654) # EPSG:32654 = WGS84 / UTM zone 54N

# Warp オプションを設定(1m 解像度)
    warp_options = gdal.WarpOptions(
    dstSRS=srs.ExportToWkt(),
    xRes=1,
    yRes=1,
    resampleAlg=gdal.GRIORA_Cubic
)

# Warp 実行
dst_ds = gdal.Warp("kakuda_1m_utm.tiff", src_ds, options=warp_options)
dst_ds = None
--------------------------------------------

この script を実行するには.....

内包された GDAL のカレントディレクトリは
---<pythonで>------------------------------------------
>>>import os
>>>print(os.getcwd())
---------------------------------------------------
で,必要により ディレクトリの変更した
---------------------------------------------------------
>>>os.chdir('C:/Users/Yasushi/SynologyDrive/Minecraft')
-------------------------------------------------------

で,実行するには
① >>> に全部貼り付けてenter
② QGISのpython console で エディタの表示をすると右のペインにコードエディタが現れるので,ここでpyファイルを読み込む.で,実行

(外のpythonでも pip install gdal や pip install osr が出来れば,外の python でもできるのだろう)

Pythonを使用して数値標高モデル(DEM)からMinecraftの地形を作成する
次に xyz 変換 これも quitq 参考 (C:/Users/Yasushi/SynologyDrive/Minecraft/2_chgAxisByPython(ByPyQGIS).py)
適宜indent 要る
------------------------------------------------------------------
# ライブラリのインポート
import rasterio
import numpy as np
import pandas as pd

# 変換したラスターファイルを開く
with rasterio.open("553616_dem_1m.tiff") as src:

    # 幅と高さを取得
    width, height = src.width, src.height

    # 中心点のオフセットを計算
    # 偶数の場合は0.5、奇数の場合は0
    offset_x = 0.5 if width % 2 == 0 else 0
    offset_y = -0.5 if height % 2 == 0 else 0

    # トランスフォーメーション行列から中心座標を計算
    transform = src.transform
    center_x = transform.c + width / 2.0 * transform.a + offset_x
    center_y = transform.f + height / 2.0 * transform.e + offset_y

    # 数値標高データを取得
    data = src.read(1)

    # 各ピクセルの中心座標を取得
    y_indices, x_indices = np.indices(data.shape)
    x_coords = x_indices * transform.a + transform.c + transform.a / 2.0
    y_coords = y_indices * transform.e + transform.f + transform.e / 2.0

    # ピクセル座標と標高値を一次元化
    x_coords = x_coords.ravel()
    y_coords = y_coords.ravel()
    data = data.ravel()

    # マイクラの基準にする中心の座標を引く
    x_coords = x_coords - center_x
    y_coords = y_coords - center_y

    # y軸(北南)を反転。マイクラ座標に合わせるため
    y_coords = y_coords * -1

    # 小数点以下を排除
    x_coords = np.trunc(x_coords).astype(int)
    y_coords = np.trunc(y_coords).astype(int)
    data = np.trunc(data).astype(int)

    # マイクラのブロック座標からregion(.mca)のファイル名を取得
    region_x = (x_coords // 512).astype(int)
    region_z = (y_coords // 512).astype(int)

    # 文字列に変換
    region_x_str = np.char.mod("%d", region_x)
    region_z_str = np.char.mod("%d", region_z)

    # ベクトル化した文字列フォーマット操作を適用
    region = np.vectorize("r.{}.{}.mca".format)(region_x, region_z)

    # データフレームを作成
    df = pd.DataFrame({
        "x": x_coords,
        "z": y_coords,
        "y": data,
        "region": region
    })

------------------------------------------------------------------

 

今後の予定は

xyzにして,それをもとにして setblock していく

CoPilot に聞いて
df.to_csv("output_dem.xyz", sep=" ", index=False, header=False)
を加えて csv を作る

[csv] 何だから separatoe がblank では変だろうということで,separator に[,]を使う

サイズが大きくなりすぎるが,どうしよう...とりあえず

5m 解像度で作ってみたが,1m 解像度で
標高の欠損値 [-9999]を書き出さないようにする.regions もいらない
としたらどだろ
まず5m解像度で実験しよう
できたdf を標高でソートしてから,標高毎(0m 台,100m台,200m 台...にxyz に書き出す.

欠損値を省いてソートするだけなら df を作った後に
--------------------------------------------------
 # 欠損値(-9999)を除外

valid_mask = data != -9999
df = df[valid_mask]

# 標高(y)で降順ソート(高い順)
df = df.sort_values(by="y", ascending=False)

df.to_csv("kakuda_5m_utm.xyz", sep=",", index=False, header=False)
---------------------------------------------------------------

minescript でつかう script を作っていく
置き場所は
C:\Users\Yasushi\AppData\Roaming\.minecraft\minescript

ではなくて....

コマンド群をつくって実行するのが良いみたい

ここでは
C:\Users\Yasushi\AppData\Roaming\.minecraft\saves\KAKUDA\datapacks

├── pack.mcmeta
└── data/
          └── your_namespace/
                    └── functions/
                              └── teleport_and_setblock.mcfunction

なるフォルダ構成を作る
名前空間はこうしよう
data/
└── kakuda_build/
          └── functions/
                     ├── teleport_and_setblock.mcfunction
                     ├── layer_400.mcfunction
                     └── layer_401.mcfunction

pack.mcmeta には json が入る

{
    "pack": {
        "pack_format": 26,
        "description": "Kakuda terrain builder"
    }
}

今使っている 1.19.3 は [12] だというので

{
    "pack": {
        "pack_format": 12,
        "description": "Kakuda terrain builder"
    }
}
となりそう.これを pack.mcmeta として保存する

 

ここまで準備したうえで

------_mk_kakuda_function.py 取りあえずのファイル名------------------------------------------------------------------------
------この py ファイルの置き場所は-C:\Users\Yasushi\SynologyDrive\Minecraft にしてある---------------------------------
import pandas as pd

# xyz ファイルを読み込む
df = pd.read_csv("kakuda_5m_utm.xyz", names=["x", "z", "y"])

# y > 400 のフィルタ
df = df[df["y"] > 400]

# コマンドリスト
commands = []

for _, row in df.iterrows():
    x, z, y = row["x"], row["z"], row["y"]
    tp_cmd = f'tp @p {x} {y+1} {z} 180 90'
    setblock_cmd = f'setblock {x} {y} {z} minecraft:dirt'
    commands.append(tp_cmd)
    commands.append(setblock_cmd)

# ファイルに保存(例:commands.mcfunction)
with open("teleport_and_setblock.mcfunction", "w") as f:
    f.write("\n".join(commands))

"""
- tp @p x y z <yaw> <pitch> の形式で、
- yaw=180 → 南向き
- pitch=90 → 真下を見る
"""
------------------------------------------------------------------------------------
外の python でもできそうだが,pyQGIS でやろう

▲20250904 PM ここまで

できたファイルを上で準備した function を
C:\Users\Yasushi\AppData\Roaming\.minecraft\saves\KAKUDA\datapacks\kakuda_build\data\kakuda_build\functions
に置く感じ?

 

pack.mcmetaというファイルも忘れないで 文字コードはUTF-8 で
置き場所は
C:\Users\Yasushi\AppData\Roaming\.minecraft\saves\KAKUDA\datapacks\kakuda_build


{
"pack": {
"pack_format": 12,
"description": "Kakuda terrain builder"
}
}

で /reload が吉.そのあと
ゲーム内で /function your_namespace:teleport_and_setblock を実行
ここでは /function kakuda_build:teleport_and_setblock
になるかな?