ワールドボーダーを、Chunky が実際に焼き終わった範囲に追随させる Forge MOD(Minecraft 1.20.1・サーバ専用)。
プレイヤーが未生成の土地へ出ると、その場でチャンク生成が走る。地形MODを重ねた構成では 1チャンクの生成が重く、参加直後に数十秒サーバが止まる。
Chunky で事前生成しておいても、焼けた範囲の外へ出られては同じことが起きる。 ボーダーを「焼けた範囲」の内側に置き続ければ、遊んでいる最中に生成が起こらない。
この MOD は Chunky の進捗を受け取り、ボーダーをそこへ追随させる。
Chunky の進捗イベント(world / chunks / complete)
↓
半径 = 8 × √(焼けたチャンク数) ※ concentric(中心から輪を広げる順)が前提
↑ ⚠ **この前提は機械が確かめる**(下記)
↓
ボーダー = 半径 − 余白(view-distance + 2 チャンク)
↓
ネザー = オーバーワールド ÷ 8
ワールドの容量が予算(既定 45GB)を超えたら、事前生成を一時停止する。
- Chunky(必須。進捗を受け取る相手)
pattern=concentricで走らせること。⚠region順だと「ここまで焼けた」と言える瞬間が 完走時しか無く、進捗から半径を出せない- 次元ごとに独立したボーダーを持つには World Border Fixer 等が要る (バニラのボーダーは全次元で1つ)
実運用で踏んだ失敗の対策が入っている。数字にはすべて理由がある(詳細はコードの注記)。
| なぜ | |
|---|---|
| 完走したタスクには 5% の割引を掛けない | 掛けたままだと焼き終わってもボーダーが手前で止まる |
| 64ブロック以内の差では動かさない | 目標が毎回わずかにズレるので、動かし続けてしまう |
| 根拠ゼロで縮めない | 「測れなかった」と「焼けていない」は別物。遊べていた範囲が突然閉じる |
| 下限128 はスポーン周辺の内側 | 大きくすると「生成済みの場所にしか行けない」が破れる |
| ネザーは常に ÷8 ちょうど | ポータルの行き先が丸められるのを、どちら向きにも防ぐ |
| 余白は view-distance から出す | ボーダーに立つと view-distance ぶんが配られる=生成される |
止めるのは cancel ではなく pause |
cancel だと進捗が消えて再開できない |
判断は BorderPlan に切り出してある。 Minecraft も Chunky も出てこないので、
サーバを起動せずに机上で確かめられる。
元々はサーバの外で動く運用スクリプトだった。RCON で繋ぎ、サーバのログを正規表現で読んで
進捗を得ていた。Chunky が ChunkyAPI で進捗を公開していると気づいて中へ移した。
外に居たせいで抱えていた厄介事は、中に入れば全部消える。
- ログを正規表現で読む → イベントを受け取るだけ
- ログは再起動で切り替わるので region ファイルのヘッダを自前で読んでいた → 進捗は届く
- 前のワールドの残骸タスクを弾く仕掛け → そもそも読まない
- RCON →
level.getWorldBorder().setSize() - 実行環境に Python があるかを気にしていた → 依存が消える
常駐の寿命も正しくなる。 外部の常駐は「落ちても黙って止まる」という不具合を抱えるが、 ボーダーを更新する必要があるのはサーバが動いている間だけなので、 MOD の中の定期処理なら寿命がぴったり一致する。
| 作りたてのワールドを閉じる | 直径 59,999,968 → 256 |
| 焼けるにつれて広がる | 1,779チャンク→321 / 2,158→386 / 2,573→451 / 3,025→516 |
| ネザーが常に 1/8 | OW 581 / ネザー 72 |
| 再起動をまたぐ | 581 → 646 → 720(縮まない) |
| 完走で割引が外れる | 4,225チャンク・完走 → 720 |
⚠ 未確認: 予算に達したときの停止(試験で再現できていない)/ プレイヤーが居る間の挙動(Chunky Autopause が止めたとき)。
MIT
書いてあるだけでは守られない。 2026-08-18 に実際に破った——ワールドを作り直したあと
chunky start を焼き順の指定なしで叩き、region(領域ファイル単位)で走った。
⚠ 遠くから先に焼かれるので 8 × √チャンク数 が嘘の半径になり、
ボーダーが未生成の土地まで開いていた(中心から 1,488 ブロック先を焼いている状態)。
py worlds/world-3/dev/verify/check_chunky_order.py # 判定する
py worlds/world-3/dev/verify/check_chunky_order.py --self-test # ツール自身を対照で試す
⚠ 設定ファイルの pattern= を見てはいけない——走行中は古い値のままで、
実際に concentric で走っていたのに region と書いてあった。
このツールは実際に焼いている座標から判定する(concentric なら
max(|x|, |z|) ≒ √(焼けたチャンク数) / 2)。
server/play_ctl.py status が自動で回すので、ステージングサーバの様子を見るたびに鳴る。
ステージングサーバのワールドを別のもの(焼いた候補の複製)へ差し替えたあと、 このMODがボーダーを 3072 → 2866 に広げた。根拠は 「オーバーワールド 45,727 チャンク」——⚠ その数は前の世界(seedG)の焼きのものだった。
⚠ Chunky の進捗はワールドの外(config/chunky/tasks/)に在るので、
ワールドを差し替えても残る。 差し替え先に実在したのは 27,026 チャンクで、
原点まわりで全部そろっていたのは ±1,184。つまり
ボーダーの内側に未生成の土地が 498 ブロック分入った。
踏み込むとチャンク生成が走り、Dynamic Waters の山岳河川づくりで
サーバスレッドが 217 秒止まった(spark の最大tick)。
⚠ 症状は「入れるのに地形が来ない・遠景だけ見える」で、ログには何も出ない。
原因に辿り着くのに jstack が要った。
| 追加したもの | 何をするか |
|---|---|
GeneratedExtent |
region ファイルの見出しから「原点まわりで全部そろっている半径」を測る(⚠ Minecraft を知らないので机上で確かめられる。⚠ 輪ごとに見るので半径の2乗の手間で済む) |
BorderPlan.clampToGenerated |
申告から出した半径を、実測 − 余白で上から抑える。⚠ 測れなければ抑えない(「測れなかった」と「焼けていない」は別物) |
| 記録の1行 | 実測の全部そろう半径 を足した。⚠ 申告と実測のどちらが効いたのかが後から読めないと、調べ直しになる |
⚠ チャンク数では代わりにならない。 同じ数でも、輪の形に焼けているのか穴だらけなのかで 「安全に歩ける半径」は変わる。形を見るしかない。
机上(Minecraft 抜き・javac で直接コンパイル)
| 見たもの | 結果 |
|---|---|
| 実際のワールドを測る | 1,184 ブロック(play_ctl.py border の Python 実装と独立に一致) |
| 無いフォルダ | 0(=抑えない) |
| 申告 > 実測 | 実測 − 余白(9999 → 992) |
| 申告 < 実測 | 申告のまま(500 → 500) |
| 測れない(0) | 抑えない(9999 → 9999) |
| 事故の再現(申告 45,727 チャンク) | 半径 1,433 → 992(直径 1,984) |
実機(ステージングサーバ・前の世界の進捗をわざと戻して起動)
Border Keeper: ボーダー 1500 → 1984(オーバーワールド 45817 チャンク・余白 192・実測の全部そろう半径 1184)
⚠ 申告だけなら 2,870 まで開くところを 1,984 で止めた。
外から py server/play_ctl.py border でも「置いてよい上限 1984 / OK」を確認した。