Scratch拡張機能の作成
ScratchでMinecraftの建築をした際に実現できなかったことがあったので、拡張機能を自作してみました。
Minecraftへのアクセスは、今回はPython FlaskでWebサーバを起動してPythonから実施します。
この記事ではScratch側の拡張機能プログラムについて記載します。
Python側のプログラムについてはこちらの記事を参考にしてください。
ブロックの作成
下記のJapanese Scratch-Wikiを参考に拡張機能を作成していきます。
https://ja.scratch-wiki.info/wiki/Scratch_3.0の拡張機能を作ってみよう「1.下準備」「2.GUI側の設定」は上記ページに記載されている通りに実施します。
「3.基本の書式」を参考に今回は下記のブロックを作成しました。
以降で各ブロックの詳細内容について記載していきます。
現在位置を取得
このブロックではMinecraft内でのプレイヤーのxyz座標を取得します。
取得した各座標の値は「xPos」「yPos」「zPos」に格納されます。
「現在位置を取得」はブロックはスタックブロックを、「xPos」「yPos」「zPos」の各ブロックは値ブロック使用しています。
「getInfo」のblocksには下記を記載します。
- {
- opcode: 'get_Pos',
- blockType: BlockType.COMMAND,
- text: '現在位置を取得'
- },
- {
- opcode: 'get_xPos',
- blockType: BlockType.REPORTER,
- text: 'xPos'
- },
- {
- opcode: 'get_yPos',
- blockType: BlockType.REPORTER,
- text: 'yPos'
- },
- {
- opcode: 'get_zPos',
- blockType: BlockType.REPORTER,
- text: 'zPos'
- }
プログラムの内容として下記を記載します。(opcodeに対応する処理です)
「get_Pos」ではPythonで作成したプログラム側へHTTPリクエストを行い、返却された情報からxyz座標の値を取得して、「xPos」「yPos」「zPos」それぞれに格納しています。
「SERVER_HOST」はPythonで作成したプログラムのWebサーバのアドレスです。「getPos」はPythonで作成したプログラムの定義名と合わせます。
「get_xPos」「get_yPos」「get_zPos」は各値を返却します。
- async get_Pos (args) {
- let path = `${SERVER_HOST}/getPos`;
- const response = fetch(path)
- .then(res => res.text())
- .then(body => {
- const obj = JSON.parse(body)
- this.xPos = obj.xPos
- this.yPos = obj.yPos
- this.zPos = obj.zPos
- });
- }
- get_xPos () {
- return this.xPos;
- }
- get_yPos () {
- return this.yPos;
- }
- get_zPos () {
- return this.zPos;
- }
ブロックを1つ置く・ブロックを置く
「ブロックを1つ置く」では指定した座標に指定したブロックを1つ設置します。
「ブロックを置く」では(x1,y1,z1)座標から(x2,y2,z2)座標まで指定したブロックで埋めるという処理になります。
引数の数が異なるだけで実施している処理はほぼ同じため、今回は「ブロックを1つ置く」について記載します。
「getInfo」のblocksには下記を記載します。
- {
- opcode: 'setBlock',
- blockType: BlockType.COMMAND,
- text: 'ブロックを1つ置く x:[x] y:[y] z:[z] blockid:[blockid] value:[value]',
- arguments: {
- x: {
- type: ArgumentType.STRING,
- defaultValue: 0
- },
- y: {
- type: ArgumentType.STRING,
- defaultValue: 0
- },
- z: {
- type: ArgumentType.STRING,
- defaultValue: 0
- },
- blockid: {
- type: ArgumentType.STRING,
- menu: 'block_id'
- },
- value: {
- type: ArgumentType.STRING,
- defaultValue: ' '
- }
- }
- }
blockidは選択式にしたので、「menus」で設定します。
- menus: {
- block_id: {
- acceptReporters: true,
- items: this.getBlock_id()
- }
- }
「getBlock_id」で選択肢のリストを作成します。
- getBlock_id () {
- var idlist = ([]);
- for (var i = 0; i < this.blockData.length; i++){
- idlist.push(this.blockData[i][0])
- }
- return idlist;
- }
選択肢は「constructor」に下記の通り定義しています。ここに定義するブロックを増やすことで選択できるブロックが増えます。
各ブロックの数値は各ブロックのIDです。ブロックIDの詳しい値はMinecraftのWikiを参照してください。
- this.blockData = [
- ['オークの原木', 17],
- ['オークの板材', 5],
- ['オークの階段', 53],
- ['オークのドア', 64],
- ['丸石', 4],
- ['丸石の階段', 67],
- ['ガラス', 20],
- ['松明', 50]
- ];
「setBlock」ではPythonで作成したプログラム側へHTTPリクエストを行い、指定した座標に指定したブロックを設置します。
「FormData」を使用してPython側へ渡したい情報を準備し、POST形式でHTTPリクエストを行います。
本来であればエラー処理など必要ですが、今回は割愛しています。
- async setBlock (args) {
- let path = `${SERVER_HOST}/setBlock`;
- const formData = new FormData();
- formData.append("x", args.x);
- formData.append("y", args.y);
- formData.append("z", args.z);
- for(var i = 0; i < this.blockData.length; i++){
- if(this.blockData[i][0] == args.blockid){
- formData.append("blockid", this.blockData[i][1])
- }
- }
- formData.append("value", args.value);
- const response = await fetch(path, {
- method: "POST",
- body: formData,
- });
- }
Python側のプログラムを起動して、作成したブロックを実行するとMinecraftの位置情報を取得したり、ブロックを設置したりすることができます。
|
|