🎮

Node.jsでMinecraftをMicrosoftアカウントで起動する | TypeScript x nodejs

2022/01/23に公開

概要

Nodejs と TypeScript で Minecraft を Microsoft アカウントを使って起動する方法です。

環境

  • Nodejs v17.4.0

モジュール

  • minecraft-auth 1.0.29
  • minecraft-launcher-core 3.16.11

作る

とりあえず TypeScript 用のプロジェクトを初期化。

yarn init
yarn add -D typescript @types/node ts-node

ディレクトリの構成はこんな感じ

E:.
│  package.json
│  tsconfig.json
│
└─src
        index.ts

まずは認証から

準備

minecraft-authをインストールします。

yarn add minecraft-auth

作ってある Azure のアプリからアプリケーションID, シークレットの値, リダイレクトURLを取得しておきます。

ディレクトリ内に.envファイルを作成し取得した情報を記述しておきます。

.env
MS_APP_ID="{アプリケーションID}"
MS_APP_SECRET="{シークレットの値}"
MS_APP_URL="{リダイレクトURL}"

nodejs で.envを読み込むためにdotenvも追加しておきます。

yarn add dotenv

コードを書く

src/auth.tsを作成してそこに書きます。
今回はminecraft-authリポジトリ にある通り、promptを使ってターミナルから認証コードを取得するので追加しておきます。

yarn add prompt
yarn add -D @types/prompt

dotenv を使って.envファイルを読み込みます。

src/auth.ts
import dotenv from 'dotenv'
import { MicrosoftAccount, MicrosoftAuth } from 'minecraft-auth'
import prompt from 'prompt'

dotenv.config()

// ...

.envを読み込んだら Azure のアプリ情報を取得します。
一応取得できなかったときの処理も書いておいた。

src/auth.ts
// ...

const MS_APP_ID = process.env.MS_APP_ID
const MS_APP_SECRET = process.env.MS_APP_SECRET
const MS_APP_URL = process.env.MS_APP_URL

if (!MS_APP_ID || !MS_APP_SECRET || !MS_APP_URL)
    throw new Error('Missing MS_APP_ID, MS_APP_SECRET or MS_APP_URL')

// ...

minecraft-authの Microsoft アカウント用のセットアップをします。
ここを忘れると何もできなくなるので注意です。

src/auth.ts
import { MicrosoftAccount, MicrosoftAuth } from 'minecraft-auth'

// ...

MicrosoftAuth.setup(MS_APP_ID, MS_APP_SECRET, MS_APP_URL)

// ...

次に、認証用の関数を作ります。
後でminecraft-launcher-coreにも使いたいのでIUserの型に変換して返すようにします。

とりあえずminecraft-launcher-coreをインストール。

yarn add minecraft-launcher-core
src/auth.ts
import { MicrosoftAccount, MicrosoftAuth } from 'minecraft-auth'
import prompt from 'prompt'

// ...

export const Authenticate = async (): Promise<IUser> => {
  const account = new MicrosoftAccount() // アカウントのインスタンスを作成
  console.log(MicrosoftAuth.createUrl()) // 認証用webページのURLを表示

  // コンソールでcodeの入力を待つ
  prompt.start()
  const result = await prompt.get(['code'])

  await account.authFlow(result.code) // 認証
  const profile = await account.getProfile() // アカウント情報をを取得

  // minecraft-launcher-core の IUser 型に変換
  return {
    access_token: account.accessToken,
    client_token: account.refreshToken,
    uuid: profile.id,
    name: profile.name,
    user_properties: [],
  }
}

これで認証用のコードは完成です。

試す

src/index.tsを作成して、さっきの認証コードを実行してみます。

src/index.ts
import { Authenticate } from './auth'

const main = async () => {
  const account = await Authenticate()
  console.log(account)
}

ts-nodeで実行してみます。

yarn ts-node ./src/index.ts

すると URL と prompt の待機画面が表示されます。
表示されている URL にアクセスしてログインしてください。

https://login.live.com/oauth20_authorize.srf?client_id=***&response_type=code&redirect_uri=****&scope=XboxLive.signin%20offline_access
prompt: code:

ログインするとリダイレクト URL にリダイレクトされて、何も動いていない限り接続エラーになるので、その段階の URL を保存しておきます。
保存した URL の ?code=**** の **** の部分をコピーしてください。

http://localhost/?code=****

そしてコピーしたコードをプロンプトに入力し、Enter を押します。

https://login.live.com/oauth20_authorize.srf?client_id=***&response_type=code&redirect_uri=****&scope=XboxLive.signin%20offline_access
prompt: code: ****

するとアカウントの情報が表示されます。

{
  access_token: '****************************',
  client_token: '********************************************************',
  uuid: 'e8bc32e81176412e8865462474f0304d',
  name: 'ddPn08',
  user_properties: []
}

これで認証の実装は完成です。

マイクラの起動

コードを書く

src/launch.tsを作成してそこに色々書いていきます。
これもまたminecraft-launcher-coreリポジトリ にかかれているのを参考に書いていきます。


とりあえずインポートします。

src/launch.ts
import { Client, ILauncherOptions } from 'minecraft-launcher-core'
import { Authenticate } from './auth'

// ...

次に起動時のオプションを設定します。authorizationは後で追加するので、今はセットしません。

各オプションについて

Parameter Description type
authorization 認証関数。さっき作ったやつを指定 ()=>Promise<IUser>
root minecraft のデーターの保存場所。.minecraftと同じようなもの string
version.number 起動する Minecraft のバージョン string
type なんでも良い String 値 string
memory maxに最大メモリ割り当て値、minに最小メモリ割り当て値 string
javaPath 使用するJavaを指定したいときはここに書きます。なくても大丈夫です。 `string

その他細かいことはminecraft-launcher-coreのドキュメントを参照してください。

src/launch.ts
import { Client, ILauncherOptions } from 'minecraft-launcher-core'
import { Authenticate } from './auth'

// ...

const option: Omit<ILauncherOptions, 'authorization'> = {
  root: './minecraft',
  version: {
    number: '1.18.1',
    type: 'release',
  },
  memory: {
    max: '6G',
    min: '4G',
  },
  // 1.18なのでjava17を指定
  javaPath: 'C:\\Program Files\\Eclipse Adoptium\\jdk-17.0.1.12-hotspot\\bin\\java.exe'
}

// ...

起動用の関数を作ります。
アカウント情報は先に取得してから渡します。そうしないと prompt と起動ログが混ざってぐちゃぐちゃになっちゃうので;

src/launch.ts
//...


export const launch = async () => {
  const client = new Client()
  const account = await Authenticate()

  client.launch({
    authorization: new Promise(resolve => resolve(account)),
    ...option,
  })
  client.on('debug', console.log)
  client.on('data', console.log)
}


最後にsrc/index.tsを少し編集します。

src/index.ts
import { launch } from './launch'

launch()

これで起動用コードは完成です。
早速起動してみましょう。

起動

先程のsrc/index.tsを実行します。

yarn ts-node src/index.ts

すると、認証の prompt が表示されるので先ほどと同じ用に URL にアクセスしてcodeを取得し、入力してください。

https://login.live.com/oauth20_authorize.srf?client_id=***&response_type=code&redirect_uri=****&scope=XboxLive.signin%20offline_access
prompt: code: ****

するとminecraft-launcher-coreのログが出力されます。
ダウンロードはかなり時間がかかるのでそのまま待ちましょう。

[MCLC]: Using Java version 17.0.1 64-bit
[MCLC]: Set native path to E:\\path\\to\\project\\minecraft\\natives\\1.18.1
[MCLC]: Collected class paths
[MCLC]: Using ; to separate class paths
[MCLC]: Attempting to download assets

しばらくすると Minecraft のログが表示されるようになります。

[09:20:03] [Render thread/INFO]: Setting user: ddPn08

[09:20:03] [Render thread/INFO]: Backend library: LWJGL version 3.2.2 build 10

[09:20:09] [Render thread/INFO]: Narrator library for x64 successfully loaded

[09:20:09] [Render thread/INFO]: Reloading ResourceManager: Default

そして無事 Minecraft が起動すれば成功です。

まとめ

minecraft-launcher-coreminecraft-authを使えば、少ないコードで簡単に実装できます。
ただ、これを Electron とかでランチャーにするとなると、Java のエラーだったり、Forge のエラーだったり、かなりいろいろな壁にぶち当たるので、ぜひぜひ頑張ってください;

Discussion