Minecraft統合版サーバーを無料で立ち上げる

フレンド向けにXServerVPSの完全無料VPSサービスを使ってMinecraft統合版(Bedrock)の構築を行った。

完全無料でMinecraftの24時間稼働サーバーを構築した備忘録。 特定ユーザーのオンラインをDiscordにWebhookで通知するコードも載せておく。

初心者の方へ。

XServerVPSではアプリイメージを使ってサーバー構築をワンボタンで行えます。
また、マインクラフトマネージャーが用意されているため、権限付与やコマンド入力、サーバーの再起動なども全部ウェブ上のUIから行えます。
サーバーファイル(server.properties)の編集を伴う設定のみLinux(Ubuntu22.04)上でのコマンド操作が必要になりますが、デフォルトの状態で問題なく遊べます。

XServerVPSの登録

XServerの無料VPSページから新規登録した。

無料VPSにもメモリが2GBと4GBの2種類あって、更新しなければいけない間隔に違いがある。 2GBは4日おきの更新に対して、4GBは2日おきの更新となる。

更新を怠るとサーバーが削除される上に、この更新はいっさいの自動化が認められていない。 したがって、2GBで事足りるなら2GBにしておくのが運用していくのに楽だろう。 今回は「フレンドと2人だけの常時稼働ワールド」という前提だったので、2GBの方で契約した。

完全無料ではあるものの、契約自体にはクレジットカード登録が必要になる。
また、1人で複数の無料VPS登録はできない。

サーバー構築

今回はPS5でマルチプレイできて常時稼働していればいいということで、Minecraft統合版のアプリイメージを使ってサーバー構築に関しては手間を省いた。

他にも「Fabric」「Forge」「JAVA」「Mohist」「NeoForge」「Paper」「Purpur」「Spigot」「SpongeVanilla」が選択できる。

マインクラフトマネージャーでの設定

自動インストール完了後、管理画面のVPS管理タブを開くと、マインクラフトマネージャーのリンクがある。 クリックするとBasic認証でのログインが求められるが、IDとパスワードは登録メールアドレスに送られている。

各種設定/情報

まずはじめにゲームモードと難易度を好みのものに設定する。 Minecraftをやったことがないからよくわからないため、一応ワールドマップ再生性も行った。 マインクラフトサーバーを再起動させてワールドの設定は完了。

ホワイトリスト

ホワイトリストを有効にして「ユーザー追加」ボタンからユーザー名を入れると、うっかり他の人がサーバーにアクセスすることがなくなる。 身内で遊ぶならこれは絶対に有効にしたほうが良い。

権限

ユーザー名を指定してオペレーター権限を付与できる。 オペレーター権限が付与されたユーザーはゲーム内のチャットからコマンドで色々な設定を変更可能になる。

身内で全員オペレーター権限があったほうが便利な場合は全員に付与、自分だけで良い場合は自分に付与するか、マインクラフトマネージャーの「コンソール」タブでもコマンドが送れるので未設定でも構わない。

ここで設定したオペレーター権限は/opt/minecraft/server/permissions.jsonに保存される。 xuidが取得できているのであれば最初からそちらを編集しても構わない。

バックアップ

自動バックアップ設定を有効、保持数は14に設定する。

コンソール

ゲームサーバーにコマンドを送信できる。 gameruleコマンドについては後述する。

個人的に設定したコマンドは以下。 オペレーター権限をもったユーザーがゲーム内チャットからコマンドを送る場合、コマンドの先頭に/を付与すること。

# プレイ日数表示
gamerule showDaysPlayed true

# 1人で寝ても朝にする

gamerule playerssleepingpercentage 0 

ゲームサーバーの設定

ゲームサーバーの設定ファイルは/opt/minecraft/server/server.propertiesに保存されている。

これはLinux(Ubuntu22.04)のコンソールからコマンド操作してやる必要がある。 コンソールは管理画面のVPS管理タブから開ける。 rootなので操作に注意する必要がある。

server.propertiesの編集後はサーバーの再起動をしないと反映されないので注意。

チャンク範囲

ゲーム内ではチャンク範囲が4になっていて、これを10に変更したいとの要望を受けた。 Minecraftでは16×16の“チャンク”を自分を中心に設定分(デフォルトでは4)読み込んでいて、チャンク範囲内でしか作物や木が成長しないらしい。

チャンク範囲を上げることにより効率よくプレイできるが、サーバーの負荷は大きくなるようだ。 よくview-distanceと間違えられるようなので注意。

vi /opt/minecraft/server/server.properties
 
tick-distance=10 

* view-distance\

描画距離。\
デフォルトで32だが、クライアント側の制限もあって無駄が多いらしいので減らしてもいいかも。\
重ければ24と16を段階的にテストする。

* tick-distance(必要なのはこっち)\

処理が行われる範囲。\
デフォルトで4だが10に変更した。推奨は8あたりらしい。\
動けば10のまま、重ければ段階的に減らす。

今回は2人プレイなのもあって10でも特に重くならないようだった。

gameruleコマンド一覧

どのようなgameruleコマンドが存在するかは、マインクラフトコンソールでgameruleと入力するとコマンド一覧と現在の値が出力される。 Minecraft1.21.124.2、マインクラフトマネージャー2.3.3での結果は以下の通り。 (現在値はデフォルト値から要望に応じて変更されている箇所あり)

gamerule 現在値 説明(未検証)
commandBlockOutput true コマンドブロック実行結果をチャットに表示
doDayLightCycle true 昼夜サイクルを進行させる
doEntityDrops true Mobやアイテムがドロップする
doFireTick true 火が燃え広がる/消える
recipesUnlock true 新アイテム入手でレシピ自動解禁
doLimitedCrafting false 解禁済みレシピ以外のクラフト禁止
doMobLoot true Mobが戦利品を落とす
doMobSpawning true Mobが自然スポーンする
doTileDrops true ブロック破壊時にアイテムが落ちる
doWeatherCycle true 天候が変化する
drowningDamage true 溺れるダメージを受ける
fallDamage true 落下ダメージを受ける
fireDamage true 火ダメージを受ける
keepInventory false 死亡時にアイテムを保持
mobGriefing true Mobがブロックに干渉できる
pvp true プレイヤー同士の攻撃を許可
showCoordinates true 画面に座標を表示
locatorBar true ロケータマップの位置バーを表示
showDaysPlayed true プレイ日数を表示
naturalRegeneration true 自然回復(体力自動回復)あり
tntExplodes true TNTが爆発する
sendCommandFeedback true コマンド成功メッセージを表示
maxCommandChainLength 65535 コマンドブロックチェーン最大実行数
doInsomnia true 夜更かしでファントムが出現
commandBlocksEnabled true コマンドブロック使用を許可
randomTickSpeed 1 ランダムティック速度
doImmediateRespawn false 死亡後に即時リスポーン
showDeathMessages true 死亡メッセージを表示
functionCommandLimit 10000 function 最大コマンド実行数
spawnRadius 10 スポーン地点の半径
showTags true プレイヤー名のタグを表示
freezeDamage true 凍結ダメージを受ける
respawnBlocksExplode true 爆発でブロックが壊れる
showBorderEffect true ワールドボーダーの視覚効果表示
showRecipeMessages true レシピ解禁メッセージ表示
playersSleepingPercentage 0 夜スキップに必要な睡眠割合
projectilesCanBreakBlocks true 発射物がブロックを破壊できる
tntExplosionDropDecay false 爆発時のドロップ減衰を有効

ログイン通知スクリプト

フレンドのログインが知りたい!という要望を受けたのでログイン通知用のスクリプトをPythonで書いた。

* DiscordのWebhookを取得してWEBHOOK_URLに設定すること * TARGET_USERSにログインを検出したいユーザーIDを設定すること。複数設定可。 * latest.logのパスが/opt/minecraft/server/latest.logであるか一応確認し、違ったら正しいパスに変更すること。

ソースコード

#!/usr/bin/env python3
import time
import re
import requests
 
LOG_PATH = "/opt/minecraft/server/latest.log"
WEBHOOK_URL = "webhook url"
TARGET_USERS = ["username"]
 
connected_pattern = re.compile(r"Player connected: ([^,]+)")
disconnected_pattern = re.compile(r"Player disconnected: ([^,]+)")
 
def send_discord_message(content: str):
try:
r = requests.post(WEBHOOK_URL, json={"content": content}, timeout=5)
print(f"[Discord] HTTP {r.status_code}")
except Exception as e:
print("[Discord] 送信エラー:", e)
 
def main():
print("Minecraftログ監視開始:", LOG_PATH)
 
```
with open(LOG_PATH, "r", encoding="utf-8", errors="replace") as f:
    f.seek(0, 2)
 
    while True:
        line = f.readline()
        if not line:
            time.sleep(0.1)
            continue
 
        line = line.rstrip("\n")
        # Debug
        print("[LOG]", line)
 
        m = connected_pattern.search(line)
        if m:
            name = m.group(1).strip()
            if name in TARGET_USERS:
                msg = f"{name} がMinecraftにログインしました!"
                print("[ACTION]", msg)
                send_discord_message(msg)
```
 
if **name** == "**main**":
main() 

通知時にメンションをつけたい場合は40行目のmsg行を以下のように編集。

msg = f"<@DiscordユーザーID>\n{name} がMinecraftにログインしました!"

サービス登録

/etc/systemd/systemディレクトリ内にminecraft-logwatch.serviceとして以下の内容で保存した。 今回は上記スクリプトを/root/login.pyとしてめちゃ適当に保存しているので、[Service]のExecStartのパスを各々書き換えること。

[Unit]
Description=Minecraft login watch notifier
After=network.target
 
[Service]
ExecStart=/usr/bin/python3 /root/login.py
Restart=always
User=root
 
[Install]
WantedBy=multi-user.target 

その後、systemctl start minecraft-logwatch.serviceで起動後、systemctl status minecraft-logwatch.serviceで有効確認。

ゲームサーバーの再起動に伴って補足できなくなった場合は以下のコマンドで再起動する。

systemctl restart minecraft-logwatch.service