Skip to content

クライアント活用例 ​

ここでは createClient() を使って書ける実用的なボットの例をまとめます。各例はコピーしてそのまま動くことを意識していますが、接続先のサーバーの仕様に合わせて調整してください。

基本形: 接続 + チャットのオウム返し ​

リポジトリの examples/client/client.js と同じ構成です。受信したチャットに返信します。

js
const bedrock = require('bedrock-protocol')

const client = bedrock.createClient({
  host: 'localhost',
  port: 19132,
  username: 'Notch',
  offline: true // オフライン(認証なし)で接続
})

client.on('join', () => console.log('参加しました'))
client.on('spawn', () => console.log('ワールドに出現しました'))

// 他人のチャットに反応してオウム返し
client.on('text', packet => {
  if (packet.source_name !== client.username) {
    client.queue('text', {
      type: 'chat',
      needs_translation: false,
      source_name: client.username,
      xuid: '',
      platform_chat_id: '',
      filtered_message: '',
      message: `${packet.source_name} said: ${packet.message}`
    })
  }
})

参加者への自動挨拶 ​

add_player パケットでプレイヤーの参加を検知して挨拶します。

js
client.on('add_player', packet => {
  client.queue('text', {
    type: 'chat',
    needs_translation: false,
    source_name: client.username,
    xuid: '',
    platform_chat_id: '',
    filtered_message: '',
    message: `ようこそ、${packet.username}!`
  })
})

コマンドの実行と応答の受け取り ​

command_request を送り、自分で生成した UUID で command_output を突き合わせます。

js
const { randomUUID } = require('crypto')

const uuid = randomUUID()
client.on('command_output', packet => {
  if (packet.origin.uuid === uuid) {
    console.log('コマンド結果:', packet.output)
  }
})

client.queue('command_request', {
  command: '/list',
  origin: {
    type: 'player',
    uuid,
    request_id: '',
    player_entity_id: 0n // 1.21.130 以降は必須
  },
  internal: false,
  version: 'latest' // 1.26.x では文字列 'latest'(1.21.x 以下は varint の数値)
})

バージョン依存の注意

version と origin.player_entity_id はバージョンで扱いが変わります。詳細はクライアントガイドの注意点を参照してください。

オンライン認証(デバイスコード) ​

オンラインモード(offline: false が既定)では Microsoft アカウントのサインインが必要です。onMsaCode で認証 URL / コードを受け取り、ユーザーに提示できます。

js
const client = bedrock.createClient({
  username: 'Notch',
  onMsaCode: data => {
    console.log(`ブラウザで ${data.verification_uri} を開き、コード ${data.user_code} を入力してください`)
  }
})

2 回目以降は profilesFolder(既定 .minecraft)にキャッシュされたトークンで自動認証されるため、認証 URL は出ません。

全パケットのダンプ ​

'packet' イベントで受信パケットをすべて観察できます。プロトコルの解析や、サーバーの実装確認に便利です。

js
client.on('packet', ({ name, params }) => {
  console.log(`[受信] ${name}`)
  // 特定パケットだけ詳細表示
  if (name === 'add_player') console.log(JSON.stringify(params, null, 2))
})

// 送信パケットも見たい場合は inLog / outLog を差し替え
// client.inLog = (...args) => console.log('[受信]', ...args)
// client.outLog = (...args) => console.log('[送信]', ...args)
// または process.env.DEBUG = 'minecraft-protocol' で全ログ出力

サーバー監視ボット(ping 定期実行) ​

ボットを接続させずに、サーバーの人数・バージョンを定期取得できます。

js
const { ping } = require('bedrock-protocol')

const TARGET = { host: 'play.cubecraft.net', port: 19132 }

async function monitor() {
  try {
    const s = await ping(TARGET)
    console.log(`[${new Date().toLocaleTimeString()}] ${s.motd} — ${s.playersOnline}/${s.playersMax} 人 (${s.version})`)
  } catch (err) {
    console.log('応答なし:', err.message)
  }
}

monitor()
setInterval(monitor, 30_000)

自動再接続(ダウン時リトライ) ​

kick / close / error を拾って再参加する、常駐ボットの基本形です。

js
const batching = { host: 'localhost', port: 19132, username: 'AutoBot', offline: true }

function login() {
  const client = bedrock.createClient(batching)

  client.on('spawn', () => console.log('復帰しました'))

  client.on('kick', packet => {
    console.log('キックされたので再接続:', packet.message)
    setTimeout(login, 5000)
  })

  client.on('close', () => {
    console.log('切断。5 秒後に再接続します')
    setTimeout(login, 5000)
  })

  client.on('error', err => console.log('エラー:', err.message))
}

login()

多重接続に注意

再接続ループで error と close の両方が発火するケースがあるため、タイマーは何重にも積まないよう、フラグでガードするのが安全です。

接続を手動制御(delayedInit) ​

接続前に ping や事前チェックを挟みたい場合は、Client クラスを直接使います。

js
const { Client } = require('bedrock-protocol')

const client = new Client({
  host: '127.0.0.1',
  port: 19132,
  username: 'Notch',
  offline: true,
  delayedInit: true // コンストラクタ時点での自動初期化を止める
})

client.init() // シリアライザ等を準備して connect_allowed を発火

client.once('connect_allowed', async () => {
  // 接続先を動的に変えたり、事前チェックしたりできる
  await client.ping() // 疎通確認(失敗時は例外)
  client.connect()
})

詳細は低レベル API のガイドを参照してください。

Realm への接続 ​

host / port を書かずに realms オプションで接続します。

js
const client = bedrock.createClient({
  username: 'Notch',
  // realmId / realmInvite / pickRealm のどれかで指定
  realms: {
    pickRealm: async realms => realms.find(r => r.name === 'My Realm')
  }
})

詳細はRealms ガイドを参照してください。

切断 ​

js
client.close()      // 即座に切断
client.disconnect() // disconnect パケットを送ってから切断

組み合わせ例: 留守番ボット ​

チャットを受信してコマンドに応答する、1 ファイルのミニボットです。

js
const bedrock = require('bedrock-protocol')

const client = bedrock.createClient({ host: 'localhost', port: 19132, username: 'Butler', offline: true })

const say = message => client.queue('text', {
  type: 'chat', needs_translation: false, source_name: client.username,
  xuid: '', platform_chat_id: '', filtered_message: '', message
})

client.on('text', ({ source_name, message }) => {
  if (source_name === client.username) return
  const m = message.toLowerCase()

  if (m.includes('おはよう')) say('おはようございます!')
  else if (m.includes('時間')) say(`今は ${new Date().toLocaleTimeString()} です`)
  else if (m === '!ping') say('応答します:pong')
  else say(`${source_name} さんの発言「${message}」を受け取りました`)
})

注意: メッセージ送信の type ​

text パケットは双方向で、type の意味が方向ごとに異なります。

  • 下り(サーバー → クライアント): type で表示様式を選ぶ(詳細はRelay ガイドの表)。
  • 上り(クライアント → サーバー): バニラクライアントが送るのは実質 'chat' のみ。サーバーは上りの type を見て、'chat' なら「プレイヤー発言」として通常のチャット(ブロードキャスト・ログ・コマンド処理)に入れます。

したがって、bot でチャット欄に発言として送りたい場合は必ず type: 'chat' を使い、source_name に自分のユーザー名を入れます。'system' や 'raw' は表示専用の type なので、上りで送るとサーバーに無視されたり想定外の扱いをされたりします。