文書アーカイブ > MotchiyのQiita? > マイクラ鯖をDiscordから起動する

目的

Discordボットを使ってMinecraftサーバを操作できるようにする

準備

以下の導入が済んでいることを前提として話を進めていきます。

  • Discordボット
  • Minecraftサーバ
  • tmux
  • Java
  • Python3

※この記事では上記すべてのやり方を解説しません。

実行環境

OS

Ubuntu Server 24.04.1 LTS

Minecraftサーバ

CurseForge for Minecraft 1.16.5 - 36.2.34

Java

OpenJDK 11.0.25

(2025/01/13 時点)

結論

以下のコードを実行することで操作ができます。

discordbot.py
# This example requires the 'message_content' intent.
 
import discord
import subprocess
 
intents = discord.Intents.default()
intents.message_content = True
 
client = discord.Client(intents=intents)
command = []
def execute(shell_script):
    subprocess.run(shell_script, shell=True)
 
@client.event
async def on_ready():
    print(f'We have logged in as {client.user}')
 
@client.event
async def on_message(message):  # メッセージへの対応
    if message.author.bot:  # 送信者がBOTのとき
        return
    elif message.content.strip():  # メッセージが空白でないとき
        try:
            await message.channel.send('wait...')
            command = message.content.split()
            match command[0]:
                case 'open':    # 先頭がopenのとき
                    await message.channel.send('now '+command[0]+'ing...')
                    execute('tmux new -s '+command[1]+' -d')
                    execute('tmux send-keys -t '+command[1]+' "cd server/'+command[1]+'"'+' ENTER')
                    execute('tmux send-keys -t '+command[1]+' "java -Xms2G -Xmx12G -jar forge-1.16.5-36.2.34.jar" ENTER')
                case 'close':   # 先頭closeのとき
                    execute('tmux send-keys -t '+command[1]+' "stop" ENTER')
                    execute('tmux send-keys -t '+command[1]+' "exit" ENTER')
        except Exception as e:  # エラーが発生したとき
            await message.channel.send(f'error: {e}')
    else:
        return
 
with open('token.txt', encoding='utf-8') as f:
    client.run(f.read())   # Discordにログイン
 

使い方

1. ディレクトリ構成をそろえる

上記のdiscordbot.pyと同じディレクトリに token.txt と server ディレクトリを作成する。

ディレクトリ構成
┝ discordbot.py
┝ token.txt
└ server
 

2. Minecraftサーバを準備する

server ディレクトリから1段階深いディレクトリにサーバのjarファイルがくるようにする。

ディレクトリ構成(一部省略)
┝ discordbot.py
┝ token.txt
└ server
    └ 250113_test
        ┝ config
        ┝ eula.txt
        ┝ forge-1.16.5-36.2.34.jar
        ├ minecraft_server.1.16.5.jar
 

3. token.txtにDiscordボットのトークンをペーストする

token.txt
s3dfD3ydf...
 
※余計なことは書かない!

4. 実行するときのコマンドを書き換える

discordbot.py(前後省略)
@client.event
async def on_message(message):  # メッセージへの対応
    if message.author.bot:  # 送信者がBOTのとき
        return
    elif message.content.strip():  # メッセージが空白でないとき
        try:
            await message.channel.send('wait...')
            command = message.content.split()
            match command[0]:
                case 'open':    # 先頭がopenのとき
                    await message.channel.send('now '+command[0]+'ing...')
                    execute('tmux new -s '+command[1]+' -d')
                    execute('tmux send-keys -t '+command[1]+' "cd server/'+command[1]+'"'+' ENTER')
                    execute('tmux send-keys -t '+command[1]+' "java -Xms2G -Xmx12G -jar forge-1.16.5-36.2.34.jar" ENTER')
 
上記のうち一番下の "java -Xms2G -Xmx12G -jar forge-1.16.5-36.2.34.jar" 部分を書き換える。

①サーバファイル

forge-1.16.5-36.2.34.jar をサーバファイル名(拡張子含む)に書き換え

②最小メモリ容量

-Xms2G を割り当てる最小のメモリ容量に書き換え
例)-Xms1G -Xms4G

③最大メモリ容量

②最小メモリ容量と同様、-Xmx12G を割り当てる最大のメモリ容量に書き換え

5. discordbot.pyを実行

シェルから以下のコマンドを実行する。

python3 discordbot.py

解説

import discord
ディスコードボットを動かすために必要なモジュール

import subprocess
Pythonからシェルコマンドを実行するために必要

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
ディスコードボットの設定

command = []
送られたメッセージリスト型にする先をつくる

def execute(shell_script):
    subprocess.run(shell_script, shell=True)
 
シェルでのコマンドを使いやすくする

@client.event
async def on_ready():
    print(f'We have logged in as {client.user}')
 
適切にディスコードへとログインできたかの確認

@client.event
async def on_message(message):  # メッセージへの対応
    if message.author.bot:  # 送信者がBOTのとき
        return
 
ボット同士で会話しないようにする

elif message.content.strip():  # メッセージが空白でないとき
    try:
        await message.channel.send('wait...')
    except Exception as e:  # エラーが発生したとき
        await message.channel.send(f'error: {e}')
else:
    return
 
何かしらの読み取れるメッセージが送られたとき、wait... と返信する

command = message.content.split()
 
メッセージを区切ってリスト型に変換

match command[0]:
    case 'open':    # 先頭がopenのとき
    case 'close':   # 先頭closeのとき
 
メッセージの先頭がopen のときとclose のときの分岐

await message.channel.send('now '+command[0]+'ing...')
 
ディスコードにnow opening... やnow closeing... と送信
closeingのスペルがおかしいのは無視

execute('tmux new -s '+command[1]+' -d')
 
tmuxで新しいセッションを作る
(subprocessをそのまま使うと鯖にstopコマンドが使えなくなってしまうため)

execute('tmux send-keys -t '+command[1]+' "cd server/'+command[1]+'"'+' ENTER')
 
サーバーディレクトリに移動

execute('tmux send-keys -t '+command[1]+' "java -Xms2G -Xmx12G -jar forge-1.16.5-36.2.34.jar" ENTER')
 
マイクラサーバーを起動

execute('tmux send-keys -t '+command[1]+' "stop" ENTER')
 
マイクラサーバーを停止

execute('tmux send-keys -t '+command[1]+' "exit" ENTER')
 
tmuxのセッションを停止

with open('token.txt', encoding='utf-8') as f:
    client.run(f.read())   # Discordにログイン
 

おわりに

最後まで読んでいただき、ありがとうございます。
何か不具合や要望がありましたら、気軽に連絡してください。

参考記事


メタデータ

最終更新:2025年09月02日 14:54