【GCP】在GCE上搭建Java版Minecraft服务器【Java版Minecraft】

总结

第三个解决GCP上构建的集成版Minecraft服务器问题。

这次我们要将服务器从Minecraft的整合版转换为Java版。

的目的

    前回までに構築していた統合版Minecraftサーバーを、Java版に変更する。

预先调查

プラグイン対応について
いろいろ試したが、統合版では現状いろいろ無理…という結論になった。
PMMP:起動、複数ワールド管理は出来たが、mobが沸かない。PureEntitiesX のPM4対応待ち?
LiteLoaderBDS:wine併用がめんどくさい、ドキュメントが中国語でわからん……。
BDSX:起動までは出来たが、プラグインの入れ方がわからんというか、npmで入れるのはわかるんだが、複数ワールドを管理するようなプラグインが見つからなかった。

Java版Minecraftサーバー
プラグインやmodはJava版の方が充実しており、mobのスポーンや、統合版クライアントからの接続も実用レベルっぽかったので、ダメ元でこちらを構築してみることにする。
これも統合版と同じくというか、それ以上に様々な種類の非公式サーバーが存在するのだが、老舗でプラグイン数も多い「Spigot」をまずは試してみる。

公式サイトは下記。
SpigotMC – High Performance Minecraft

1. 建立

将已构建的Minecraft集成服务器(官方版)替换为Spigot。

1.1. 代码修正

Minecraft服务器的建立是通过cloud-init(cloud-config)来实施的,因此需要对其进行修正。

service01\templates\cloud-init.yamlservice01\templates\cloud-init.yaml
#cloud-config
timezone: 亚洲/东京
locale: ja_JP.utf8
packages:
– openjdk-17-jre-headless
– expect
– apache2
– unzip
– zip

users:
– name: ‘minecraft’
plain_text_passwd: ‘minecraft’
shell: ‘/bin/bash’
sudo: ‘ALL=(ALL) NOPASSWD:ALL’
lock_passwd: false

runcmd:
– mkdir /opt/minecraft
– mkdir /opt/minecraft/backup_worlds
– mv /home/minecraft/mcs_backup.sh /opt/minecraft/mcs_backup.sh
– mv /home/minecraft/spigot_init.sh /opt/minecraft/spigot_init.sh

write_files:
– path: /home/minecraft/mcs_backup.sh
content: |
#!/bin/bash
screen -r tskserver -X stuff ‘/save-all\n/save-off\n’

WORLDS=(hoge)
BACKUP_BUCKET=’gs://hoge/’

for world in ${WORLDS[@]}; do
cp -r ${BASH_SOURCE%/*}/${world} ${BASH_SOURCE%/*}/backup_worlds/
done

/usr/bin/zip -r ${BASH_SOURCE%/*}/backup_worlds.zip ${BASH_SOURCE%/*}/backup_worlds
/snap/bin/gsutil cp -R ${BASH_SOURCE%/*}/backup_worlds.zip ${BACKUP_BUCKET}
/bin/rm ${BASH_SOURCE%/*}/backup_worlds.zip

screen -r tskserver -X stuff ‘/save-on\n’
permissions: ‘0755’
owner: root:root
– path: /home/minecraft/spigot_init.sh
content: |
#!/bin/bash
# おまじない
cd `dirname $0`

# 必要ファイルをDL
wget -P /opt/minecraft https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
wget -P /opt/minecraft/plugins https://ci.lucko.me/job/LuckPerms/1429/artifact/bukkit/loader/build/libs/LuckPerms-Bukkit-5.4.21.jar
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/dynmap/files/latest
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/worldedit/files/latest
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/WorldGuard/files/latest
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/Multiverse-Core/files/latest
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/Multiverse-Portals/files/latest
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/multiverse-inventories/files/latest
wget –trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/Multiverse-NetherPortals/files/latest
wget -P /opt/minecraft/plugins https://ci.opencollab.dev//job/GeyserMC/job/Geyser/job/master/lastSuccessfulBuild/artifact/bootstrap/spigot/target/Geyser-Spigot.jar
wget -P /opt/minecraft/plugins https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/lastSuccessfulBuild/artifact/spigot/target/floodgate-spigot.jar
wget -P /opt/minecraft/plugins https://github.com/Camotoy/GeyserSkinManager/releases/download/1.6/GeyserSkinManager-Spigot.jar
wget -P /opt/minecraft/plugins https://ci.viaversion.com/job/ViaVersion/lastBuild/artifact/build/libs/ViaVersion-4.2.2-SNAPSHOT.jar
wget -P /opt/minecraft/plugins https://ci.viaversion.com/view/ViaBackwards/job/ViaBackwards/lastBuild/artifact/build/libs/ViaBackwards-4.2.1.jar
wget -P /opt/minecraft/plugins https://ci.viaversion.com/view/ViaRewind/job/ViaRewind/lastBuild/artifact/all/target/ViaRewind-2.0.3-SNAPSHOT.jar

# ビルド
while [ ! -e BuildTools.jar ] ; do sleep 10; done && java -jar BuildTools.jar –rev latest

# ビルド終了まで待つ
while [ ! -e spigot-* ] ; do sleep 10; done

# metadata_startup_script の起動を簡易化する(バージョンに依存させない)ためにリネーム(コピー)
ver_num=`ls | grep spigot- | cut -c 8- | rev | cut -c 5- | rev`
cp spigot-${ver_num}.jar spigot.jar

# 初回起動
java -Xms1024M -Xmx8G -jar spigot.jar nogui

# eula 同意、server.properties 変更
sed -i”.org” -e “s/^online-mode=true$/online-mode=false/g” /opt/minecraft/server.properties
sed -i -e “s/level-name=world$/level-name=lobby/g” /opt/minecraft/server.properties
sed -i -e “s/server-port=25565$/server-port=19132/g” /opt/minecraft/server.properties
sed -i -e ‘$ a server_name=”hoge”‘ /opt/minecraft/server.properties
sed -i”.org” -e “s/eula=false$/eula=true/g” /opt/minecraft/eula.txt

# 2回目起動
java -Xms1024M -Xmx8G -jar spigot.jar nogui

# プラグインの設定変更
sed -i”.org” -e “s/clone-remote-port: false$/clone-remote-port: true/g” /opt/minecraft/plugins/Geyser-Spigot/config.yml
sed -i -e “s/auth-type: online$/auth-type: floodgate/g” /opt/minecraft/plugins/Geyser-Spigot/config.yml
sed -i -e ‘s/server-name: “Geyser”$/server-name: “hoge”/g’ /opt/minecraft/plugins/Geyser-Spigot/config.yml
sed -i -e “s/passthrough-motd: false$/passthrough-motd: true/g” /opt/minecraft/plugins/Geyser-Spigot/config.yml
sed -i -e “s/passthrough-player-counts: false$/passthrough-player-counts: true/g” /opt/minecraft/plugins/Geyser-Spigot/config.yml

# サーバー再起動
reboot
permissions: ‘0755’
owner: root:root
– path: /var/www/html/index.html
content: |
<!doctype html>

permissions: ‘0644’
owner: root:root

# reboot
#power_state:
# delay: “+15”
# mode: reboot

由于结构发生了巨大的变化,我们将每个区块进行解释(或者说备注)如下所示,runcmd: 。

runcmd:
  - mkdir /opt/minecraft
  - mkdir /opt/minecraft/backup_worlds
  - mv /home/minecraft/mcs_backup.sh /opt/minecraft/mcs_backup.sh
  - mv /home/minecraft/spigot_init.sh /opt/minecraft/spigot_init.sh

由于数量增加和特殊符号转义太麻烦,我将其脚本化。
在“spigot_init.sh”中,我们进行了服务器程序、插件和各种设置的下载以及其他各种操作。
“mcs_backup.sh”是一个通常用来将世界数据备份到GCS的脚本,但由于更改了服务器程序,目录结构也有所变化,因此我们进行了一些修改(详细信息请参考后述)。
脚本的内容记录在write_files:中,rumcmd:仅包括必要的最基本的目录创建和脚本文件移动操作。

以下是备份脚本。

    - path: /home/minecraft/mcs_backup.sh
      content: |
        #!/bin/bash
        screen -r tskserver -X stuff '/save-all\n/save-off\n'

        WORLDS=(hoge)
        BACKUP_BUCKET='gs://hoge/'

        for world in ${WORLDS[@]}; do
          cp -r ${BASH_SOURCE%/*}/${world} ${BASH_SOURCE%/*}/backup_worlds/
        done

        /usr/bin/zip -r ${BASH_SOURCE%/*}/backup_worlds.zip ${BASH_SOURCE%/*}/backup_worlds
        /snap/bin/gsutil cp -R ${BASH_SOURCE%/*}/backup_worlds.zip ${BACKUP_BUCKET}
        /bin/rm ${BASH_SOURCE%/*}/backup_worlds.zip

        screen -r tskserver -X stuff '/save-on\n'
      permissions: '0755'
      owner: root:root

統合版的世界数据被整合到安装目录内的“worlds”文件夹中,而Java版会在安装目录内创建各个世界的文件夹。
因此,如果要批量备份指定目录,就必须指定安装目录,这会导致包含大量多余文件。
为了解决这个问题,我添加了将每个世界文件夹暂时复制到备份目录的步骤。
由于只有在创建世界后才知道世界名称,所以手动维护的部分也增加了……。
我曾考虑过在世界名称(文件夹名称)上添加前缀(world_)或后缀(_world),但考虑到在游戏内指定世界名称,我不希望过于冗长,所以没有采用。

以下是用于服务器初始设置的脚本。

    - path: /home/minecraft/spigot_init.sh
      content: |
        #!/bin/bash
        # おまじない
        cd `dirname $0`

        # 必要ファイルをDL
        wget -P /opt/minecraft https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
        wget -P /opt/minecraft/plugins https://ci.lucko.me/job/LuckPerms/1429/artifact/bukkit/loader/build/libs/LuckPerms-Bukkit-5.4.21.jar
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/dynmap/files/latest
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/worldedit/files/latest
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/WorldGuard/files/latest
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/Multiverse-Core/files/latest
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/Multiverse-Portals/files/latest
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/multiverse-inventories/files/latest
        wget --trust-server-names -P /opt/minecraft/plugins https://dev.bukkit.org/projects/Multiverse-NetherPortals/files/latest
        wget -P /opt/minecraft/plugins https://ci.opencollab.dev//job/GeyserMC/job/Geyser/job/master/lastSuccessfulBuild/artifact/bootstrap/spigot/target/Geyser-Spigot.jar
        wget -P /opt/minecraft/plugins https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/lastSuccessfulBuild/artifact/spigot/target/floodgate-spigot.jar
        wget -P /opt/minecraft/plugins https://github.com/Camotoy/GeyserSkinManager/releases/download/1.6/GeyserSkinManager-Spigot.jar
        wget -P /opt/minecraft/plugins https://ci.viaversion.com/job/ViaVersion/lastBuild/artifact/build/libs/ViaVersion-4.2.2-SNAPSHOT.jar
        wget -P /opt/minecraft/plugins https://ci.viaversion.com/view/ViaBackwards/job/ViaBackwards/lastBuild/artifact/build/libs/ViaBackwards-4.2.1.jar
        wget -P /opt/minecraft/plugins https://ci.viaversion.com/view/ViaRewind/job/ViaRewind/lastBuild/artifact/all/target/ViaRewind-2.0.3-SNAPSHOT.jar

        # ビルド
        while [ ! -e BuildTools.jar ] ; do sleep 10; done && java -jar BuildTools.jar --rev latest

        # ビルド終了まで待つ
        while [ ! -e spigot-* ] ; do sleep 10; done

        # metadata_startup_script の起動を簡易化する(バージョンに依存させない)ためにリネーム(コピー)
        ver_num=`ls | grep spigot- | cut -c 8- | rev | cut -c 5- | rev`
        cp spigot-${ver_num}.jar spigot.jar

        # 初回起動
        java -Xms1024M -Xmx8G -jar spigot.jar nogui

        # eula 同意、server.properties 変更
        sed -i".org" -e "s/^online-mode=true$/online-mode=false/g" /opt/minecraft/server.properties
        sed -i -e "s/level-name=world$/level-name=lobby/g" /opt/minecraft/server.properties
        sed -i -e "s/server-port=25565$/server-port=19132/g" /opt/minecraft/server.properties
        sed -i -e '$ a server_name="hoge"' /opt/minecraft/server.properties
        sed -i".org" -e "s/eula=false$/eula=true/g" /opt/minecraft/eula.txt

        # 2回目起動
        java -Xms1024M -Xmx8G -jar spigot.jar nogui

        # プラグインの設定変更
        sed -i".org" -e "s/clone-remote-port: false$/clone-remote-port: true/g" /opt/minecraft/plugins/Geyser-Spigot/config.yml
        sed -i -e "s/auth-type: online$/auth-type: floodgate/g" /opt/minecraft/plugins/Geyser-Spigot/config.yml
        sed -i -e 's/server-name: "Geyser"$/server-name: "hoge"/g' /opt/minecraft/plugins/Geyser-Spigot/config.yml
        sed -i -e "s/passthrough-motd: false$/passthrough-motd: true/g" /opt/minecraft/plugins/Geyser-Spigot/config.yml
        sed -i -e "s/passthrough-player-counts: false$/passthrough-player-counts: true/g" /opt/minecraft/plugins/Geyser-Spigot/config.yml

        # サーバー再起動
        reboot
      permissions: '0755'
      owner: root:root

這部分很麻煩的是進行 Spigot 的建置所需的「java -jar BuildTools.jar –rev latest」指令。
在 cloud-init 中執行上述腳本時,總是會由於 Java 錯誤而失敗。
嘗試在腳本內進行 JDK 的安裝,明確指定環境變數,利用迴圈等待建置結果的檔案創建,嘗試了很多方法,但都無效…
相同的腳本在正常登入伺服器後執行沒問題,因此決定手動執行本腳本。

另外,生成的可执行文件包含了版本号,在自动化启动和停止方面会造成干扰,因此我加入了一个将文件复制到不包含版本号的文件名的过程(虽然也可以进行重命名,但为了保留原始文件,就仅仅进行了复制)。

以下是Dynmap插件的用途。

    - path: /var/www/html/index.html
      content: |
        <!doctype html>
        <html lang="en">
        <head>
          <meta charset="utf-8">
          <title>Jump to Dynmap</title>
          <meta http-equiv="Refresh" content="0;URL=hoge:8123">
        </head>
        <body> </body>
        </html>
      permissions: '0644'
      owner: root:root

Dynmap是一个插件,可以在Web浏览器上查看Minecraft游戏内的地图。
因为它看起来很方便和有趣,所以我安装了它。
为了能够通过Web浏览器访问它,需要在端口8123上输入URL,所以我安装了apache,并将80端口重定向到8123端口。

在负载均衡器上接收https流量,或者在Traffic Director上进行路由等,可能还有一些更智能的方式可用,但可能需要额外费用,所以暂时就用这个吧。

另外,还对 metadata_shutdown_script 进行了一些修改。

variable "gce" {
  default = {
    dev = {
      minecraft-game-server = {
        machine_type             = "e2-standard-4"
        image                    = "ubuntu-os-cloud/ubuntu-1804-lts"
        type                     = "pd-standard"
        size                     = "10"
        block-project-ssh-keys   = true
        key_name                 = "mcs_key"
        deletion_protection      = false
        metadata_startup_script  = "cd /opt/minecraft/\nscreen -dmS tskserver java -Xms1024M -Xmx8G -jar spigot.jar nogui"
        metadata_shutdown_script = "cd /opt/minecraft/\nscreen -p 0 -S tskserver -X eval 'stuff 'say 30秒後にサーバーをシャットダウンします、ログアウトしてください\\015'\nsleep 10\nscreen -p 0 -S tskserver -X eval 'stuff 'say 20秒後にサーバーをシャットダウンします、ログアウトしてください\\015'\nsleep 10\nscreen -p 0 -S tskserver -X eval 'stuff 'say 10秒後にサーバーをシャットダウンします、ログアウトしてください\\015'\nsleep 5\nscreen -p 0 -S tskserver -X eval 'stuff 'say 5秒後にサーバーをシャットダウンします、ログアウトしてください\\015'\nsleep 5\nscreen -r tskserver -X stuff 'save-all\\015'\nscreen -r tskserver -X stuff 'stop'\n/opt/minecraft/mcs_backup.sh"
      }
    }
    prd = {
    }
  }
}

尽管只需大约30秒,但在关闭游戏之前,会进行游戏内的倒计时通知。基本上,最后退出游戏的人会从Discord发送关闭命令,或者根据CPU使用率自动关闭,所以实际上除了自我满足之外,没有其他作用……。我认为,在脚本中能够发送消息到Minecraft游戏内是一个相当有趣的功能。

1.2. 插件

基本上只需要下载和放置,因此在前面的 cloud-init(cloud-config) 中已经执行过了(虽然有些设置需要在首次服务器启动后进行)。但是 cloud-init(cloud-config) 只包含到最终更新文件的链接,所以我将在这里简要介绍一下。

已安裝的插件如下:

LuckPerms-Bukkit-5.4.21(权限管理)
Dynmap® v3.4-beta-3(通过浏览器查看Minecraft地图)
WorldEdit for Bukkit 7.2.10(地图编辑器)
worldguard-bukkit-7.0.7(区域保护等)
Multiverse-Core-4.3.1(多世界管理)
Multiverse-Portals-4.2.1(多世界传送门)
Multiverse-NetherPortals-4.2.2(下界世界管理)
Per World Inventory 2.3.2(多世界物品管理)
GeyserMC(允许连接基岩版客户端)
Floodgate(允许无需认证连接基岩版客户端)
GeyserSkinManager 1.6(应用基岩版皮肤)
ViaVersion 4.2.1(允许连接新的客户端版本)
ViaBackwards 4.2.1(允许连接旧的客户端版本)
ViaRewind 2.0.2(允许连接更旧的客户端版本)

暫時只是把可能需要的東西一個個加進去,所以說實話,我還沒跟上理解。
在玩的同時,我會進行一些調整…
關於每個插件的解說,也許等稍微理解得更多或者心情好的時候,可能會單獨寫或者可能不寫。

1.3. 驗證動作

经过确认,可以顺利登录并在PC版和Switch版之间进行世界转移。
而且mob也能正常生成和移动。
此外,从Discord进行服务器操作,自动停止功能以及世界数据备份等运营方面的功能也都能正常运行。
呼,终于能够开始游玩了,感觉一切准备工作都完成了。

顺便提一下,目前的全球构造如下。

    1. 大堂用世界

 

    1. 家庭用世界

 

    1. 公会用世界

 

    收集素材用世界

最初登录服务器后,会进入大厅用的世界,然后再通过传送门进入各个世界。暂时将2和3分开是为了方便,但如果互动增多的话,可能会合并成一个。

1.4. 补充

通过将版本更改为Java版和增加世界数量,导致闲置状态下(登录用户为0时)的CPU使用率从1%上升到约7%。
因此,将CPU使用率警报从“低于2%”更改为“低于8%”。

variable "monitoring" {
  default = {
    dev = {
      cpu_utilization_threshold = 0.08
      cpu_utilization_threshold_percent = 8
      trigger_topic         = true
      available_memory_mb   = 128
      timeout               = 120
      retry                 = true
      entry_point           = "run"
    }
  }
bannerAds