マシュマロやYouTubeのコメント欄などで多かった質問をまとめておきました。参考にしてみてください:
透明になる場合、ブロックを定義するjsonファイルに問題がある可能性が高いです。特に存在しないキーを追加した場合や間違った値が入っている場合などに起こり得ます。
一般的に、どこでエラーが起きているかが分かると解決に大きく近づきます。このエラーは、設定→クリエイター→コンテンツログGUIの有効化をオンにすると表示されるようになります。
ブロックとテクスチャーの紐づけがうまく行われていないみたいですね…
以下の3点を確認してみてください:
①リソースパックのフォルダ内にblocks.jsonがあるか
{"format_version":"1.16.100",
"test:test_block" : {
"sound" : "stone",
"textures" : "test_block"
}
}
②resource_pack/blocks内にterrain_texture.jsonがあるか
{"num_mip_levels" : 4,
"padding" : 8,
"resource_pack_name" : "lemon_pack",
"texture_data" : {
"test_block" : {
"textures" : "textures/blocks/test_block"
}
},
"texture_name" : "atlas.terrain"
}
③resource_pack/textures/blocksにテクスチャー画像(test_block.png)があるか
現状のScriptAPIは右クリック自体の検知はできますが、「右クリックしている間を継続的にトリガー」というのは難しいというのが現状です。
(beforeEvents中のアイテム使用を検知するプロパティとしてはitemUseとitemUseOnがあるが、どちらも右クリックを継続的にトリガーすることはできないため)
どうしても検知したい場合、WebSocketServerを用いて外部ライブラリ経由で右クリックをトリガーするといった方法が考えられます。例えば、Python経由でマインクラフトを制御できるbedrockpyなど:
ScriptAPIを使えば、現在オフハンド・インベントリ内にあるアイテムを取得できます。オフハンドのアイテムの検知は、
const offhandItem = ev.player.getComponent(server.EntityComponentTypes.Equippable)
.getEquipment(server.EquipmentSlot.Offhand);
というスクリプトで取得できますし、インベントリのアイテムは、
const inventoryItem = player.getComponent(server.EntityComponentTypes.Inventory).container.getSlot(0)
というスクリプトで取得できます。詳細はこちらの記事が詳しいです:
ブロックの右クリックを検知するには、ScriptAPIと「カスタムコンポーネント」を使用する必要があります。
「カスタムコンポーネント」というのは、簡単に言うと自分で自由に定義できるアイテム・ブロックのコンポーネント(構成要素)のことです。
ここでは簡単にスクリプトを書いておきますね:
server.world.beforeEvents.worldInitialize.subscribe(initEvent => {initEvent.blockComponentRegistry.
registerCustomComponent('test:custom', {
onPlayerInteract(arg){
const player = arg.player; // プレイヤーを取得
const block = arg.block; // ブロックを取得
player.sendMessage(player.name + "は" + block.typeId + "を触りました");
}
});
});
環境構築など、詳細なことはこちらの記事が詳しいです:
https://lemon-slime.com/game/minecraft/scriptapi-customcomponent-block/
CustomCommandParamType型のEnumというのは、列挙型の引数を定義するものです。
例えば「A,B,C」という選択肢を予め定義しておいて、その中から1つを選択するタイプの引数を作ることができます。
この機能を使用するためには、予めregisterEnum関数で選択肢を定義しておく必要があります。
具体的なスクリプトについては、以下の記事の「選択肢から選ぶ引数」の節で解説しています:
耐久値自体は、
"minecraft:durability":{"max_durability":60
},
のようなスクリプトをアイテムのコンポーネントに追加することで定義できます。これを減らす処理についてですが、こちらの記事:
https://lemon-slime.com/game/minecraft/addon-durability/
で詳しくまとめています。
カスタムコマンドを定義するスクリプトの中に、show_form(player)を発火させるなどして両者を組み合わせればOKです:
import * as server from "@minecraft/server";import * as ui from "@minecraft/server-ui";
server.system.beforeEvents.startup.subscribe(ev => {
ev.customCommandRegistry.registerCommand({
// ★ここは省略★
},(origin,arg) => {
show_form(origin.sourceEntity); // ★別途show_form関数の定義が必要です★
})
})
show_form関数の内容など、フォームの出し方についてはこちらでまとめています:
ダイナミックプロパティーというのは、簡単に言うと、特定のエンティティに紐づけてデータを記録する仕組みのことです。
普通、スクリプト中でletやconstのように変数を宣言・定義すると、スクリプトが読み込まれるたびにリセットされてしまいますが、ダイナミックプロパティに保存したデータは、サーバーを再起動したり、プレイヤーがログアウトしても保持されるという特徴があります。
拠点の座標のような、永続的にアクセスする変数に使うことが想定されます。
ダイナミックプロパティーの取得にはgetDynamicProperty()
を、代入にはsetDynamicProperty()
を使います。
以下のように、afterEventsプロパティのplayerBreakBlockを使えばブロックの破壊を検知できます:
import * as server from '@minecraft/server';server.world.afterEvents.playerBreakBlock.subscribe(ev => {
const player = ev.player;
const block = ev.block;
player.sendMessage(${player.name}が${block.typeId}を壊しました
);
})
あるいは、ブロック側でカスタムコンポーネントを定義するという方法も考えられます。詳細はこちら:
https://lemon-slime.com/game/minecraft/scriptapi-customcomponent-block/
自然生成する建造物を作成するには、features
とfeature_rules
の2つが必要です:
MyAddon_BP/├─ manifest.json
├─ structures/
│ └─ house.mcstructure
├─ features/
│ └─ house.json
└─ feature_rules/
└─ house.json
具体的なスクリプトについてはこちらでまとめています:
こちらの記事:
https://lemon-slime.com/game/minecraft/scriptapi-ui/
でまとめている通り、
function generate_player_list(){let player_list = [];
for (const player of server.world.getAllPlayers()){
player_list.push(player.name);
}
return player_list;
}
のようにプレイヤー名のリストを定義して、
form.dropdown("ドロップダウン",generate_player_list());
のようにdropdownの関数内で使用することで解決します。
最後に、YouTube動画を置いておきます: