文字を入力するだけで、QRコード生成コマンドを含む統合版マイクラ用アドオン(.mcpack)をワンクリックでダウンロードできるWebアプリQRコードアドオンジェネレーターを開発しました。本記事では技術的な仕組みを解説します。
ソースコードはこちら
QRコードは株式会社デンソーウェーブの登録商標です。
本アプリは Minecraft for Windows 1.21.124で動作確認を行っています。
使い方
入力欄にurlなどのQRコードにしたい文字列を入力して生成ボタンを押します。

QRコードが表示されます。ダウンロードボタンを押すと、統合版マイクラ用のアドオンがダウンロードできます。
クリックすると、マイクラが起動してインポートされます。
チートを有効化したワールドに、ビヘイビアーパックを適用します。
アイコンがQRコードになっています。
ビヘイビアーパックを適用したワールドで下記コマンドを実行します。
/function qr
白と黒のコンクリートでQRコードが生成されます。
チャンネル登録お願いします
先行研究事例
マイクラでQRコードを作る、という企画はyoutubeなどで時々見かけるテーマです。サバイバルで手置き作成することができます。
クリエイティブモードでコマンド生成する取り組みについても前例があります。
ドットやコマンドを生成するツールは既にあり
2023年のアドベントカレンダーでは、QRコード生成データパックを作成されている方がいます。
コマンドの生成までは自動化できますが、統合版マイクラで読み込むにはビヘイビアーパックに加工する必要があります。パッケージ生成まで自動化するために、Webアプリを作成しました。
技術スタック
- typescript
- Vite + React
- Tailwind
- Vibe Coding
AIは主にCopilotを使用しました。無課金です。
セカンドオピニオン要員としてはGeminiを使用しました。こちらも無課金です。
以下QRコード用コマンドの生成、アドオン生成について解説します。
QRコード生成コマンドの仕組み
QRコードの白黒を、コンクリートの白黒で再現するコマンドを作成しました。マイクラのsetblockコマンドを使用して、1ドット、1ブロックずつ設置するコマンドを作成します。
QRコード生成
はじめに、QRコード自体を生成します。ライブラリを使用しました。
QRコードの白黒の情報を得るために、BitMatrixというデータを利用します。
import QRCode from "qrcode";
/**
* 入力文字列から QRコードの 2D 配列を生成
* 黒: 1, 白: 0
*/
export function generateMatrix(text: string): QRCode.BitMatrix {
const qr = QRCode.create(text);
return qr.modules;
}
文字列からQRコードの白黒の情報を0,1の2値、2次元配列のような形式で得ることができます。ここからQRコード生成用のコマンドを組み立てます。
setblockコマンド生成
import QRCode from "qrcode";
/**
* コンクリートの色を判定する
*
* @param bit 1:黒、0:白
* @returns コンクリート
*/
function judgeConcreteColor(bit: number): string {
return bit === 1 ? "minecraft:black_concrete" : "minecraft:white_concrete";
}
/**
* コマンドの座標部分を生成する
*
* @param x 東西方向
* @param y 高さ
* @param length 左上から生成するためのオフセット
* @returns 相対座標
*/
function generateCoordinate(x: number, y: number, length: number): string {
return `~${length - x}~${length - y}~1`;
}
/**
* コマンドを組み立てる
*
* @param matrix QRコードの 2D 配列(0, 1)
* @returns setblockコマンド
*/
export function generateCommands(matrix: QRCode.BitMatrix): string {
const commands: string[] = [];
const length = matrix.size;
for (let y = 0; y < length; y++) {
for (let x = 0; x < length; x++) {
const bit = matrix.get(x, y);
const concrete = judgeConcreteColor(bit);
const coordinate = generateCoordinate(x, y, length);
const command = `setblock ${coordinate} ${concrete}`;
commands.push(command);
}
}
return commands.join("\n");
}
generateCommandsの処理イメージ

QRコードの左上のビットから順に値を取得し、0,1の値からコンクリートの種類を判定します。ビット取得の数値をsetblockコマンド用の座標に変換し、コマンドを組み立てています。
なおQRコードは文字列のデータ量によって、ドット数が多くなり、マイクラで表現しようとすると巨大になります。setblockコマンドの実行できる範囲は、シミュレーションチャンク内に限られるため、範囲外のブロックは設置できません。シミュレーション距離4チャンクの場合、4 x 16 = 64、1辺64ブロックのQRコードが生成できそうですが、実際は48ブロックまでしか収まりません。そのため、QRコードを地面に対して水平に生成すると、QRコードの角が切れてしまうことがありました。そこで、シミュレーション距離を最大限有効活用できるように、地面に対して垂直にQRコードを生成しています。
mcpack生成
作成したコマンドを、統合版マイクラにインポートできるようにビヘイビアーパックの形に整形します。
import JSZip from "jszip";
/**
* manifest.jsonを生成する
*
* @param text QRコードから読み取れる文字列
* @returns manifest.jsonの文字列
*/
function generateManifest(text:string): string {
const manifest = {
format_version: 2,
header: {
name: "QRコード生成 : " + text,
description: "「/function qr」コマンド実行でQRコードを生成します",
uuid: crypto.randomUUID(),
version: [1, 0, 0],
min_engine_version: [1, 21, 124],
},
modules: [
{
type: "data",
uuid: crypto.randomUUID(),
version: [1, 0, 0],
},
],
}
return JSON.stringify(manifest, null, 2);
}
/**
* imageのDataURLからBlobを生成
*
* @param url 画像のurl
* @returns 画像ファイル
*/
async function generateImageBlob(url:string):Promise<Blob>{
const res = await fetch(url);
return await res.blob();
}
/**
* .mcpackを生成する
*
* @param commands コマンドを繋げた文字列
* @param text QRコードから読み取れる文字列
* @param image_url QRコードの画像url
* @returns
*/
export async function generateMcpack(commands: string, text:string, image_url:string): Promise<Blob> {
const zip = new JSZip();
// コマンドファイル生成
const mcfunction = new Blob([commands], { type: "text/plain" });
zip.file("functions/qr.mcfunction", mcfunction);
// マニュフェスト生成
zip.file("manifest.json", generateManifest(text))
// アイコン生成
const icon = await generateImageBlob(image_url)
zip.file("pack_icon.png", icon)
// zipファイル生成
return zip.generateAsync({ type: "blob" });
}
generateManifest
ビヘイビアーパックの定義ファイルmanifest.jsonの生成処理です。QRコード生成に使用した文字を直接ビヘイビアパックの名前に入れています。uuidはビヘイビアーパックごと固有のidを割り当てる必要があるため、毎回生成してます。
crypto.randomUUID()
generateImageBlob
QRコードの画像をビヘイビアーパックのアイコンに直接指定しています。QRコードの画像はライブラリで生成し、Blob形式に変換しています。
import QRCode from "qrcode";
/**
* QRコードの画像を生成する
*
* @param text QRコード生成文字列
* @returns QRコードの画像url
*/
export async function generateImage(text: string):Promise<string>{
return await QRCode.toDataURL(text);
}
generateMcpack
.mcpackはzip形式のファイルの拡張子を書き換えたものです。
次のようなファイル構成に整形しています。
QRコード生成アドオン.mcpack
│ manifest.json
│ pack_icon.png
│
└─ functions
qr.mcfunction
最終的に、Blobよりダウンロードurlを生成しています。
const [downloadUrl, setDownloadUrl] = useState<string | null>(null);
// ファイル生成
const blob = await generateMcpack(commands, text, qrImage);
const url = URL.createObjectURL(blob);
setDownloadUrl(url);
<a
href={downloadUrl}
download="QRコード生成アドオン.mcpack"
>
ダウンロード
</a>
ソースコード全体はGithubをご覧ください。
デプロイ
WebアプリはGithub Pageにて公開しています。mainブランチにプッシュすると、ビルドされるGithub Actionを設定しています。
Viteのサイトに詳細な手順が載っています。こちらを参照してください。
まとめ
統合版マイクラ向けQRコードジェネレーターを作ってみました。.mcpack自動生成機能は、他のアドオンにも応用できそうです。


