悲報
タイトルにもある通り、itemとblockのevent関係が1.21.20にて消えました。
event関係をjsonで書くことができなくなってしまうのです。
itemで言うと、なんとか生きながらえていたon_useや、blockではon_interactが使えなくなってしまいます。もちろんeventsも使えなく。
このアップデートにより、多くのアドオンが使えなくなることでしょう。
しかしただ使えなくなるというだけでなく、代替機能もあります。
朗報
event関係はカスタムコンポーネントという機能で再び同じようなことが可能になります。
カスタムコンポーネントというのは、ScriptAPIという機能を使って自分だけのコンポーネントを作れるようになるというものです。
JavaScriptというプログラミング言語を使用するので慣れない人には移行の難易度が高いと思うかもしれませんが、できることも増えていくので「event関係が消えた、もうアドオンはお終いだ」と悲しいことばかりに目を向ける必要もないでしょう。
この記事では、そのカスタムコンポーネントの使用方法について解説します。役に立つ記事になったら嬉しいです。
話し始める前に
カスタムコンポーネントはScriptAPIという機能を使うので、ScriptAPIについて知識を持っておくと非常に便利です。
ScriptAPIの解説記事はいくつか出している人はいるので、なにかしらの場所である程度の知識はつけておくことを推奨します。
宣伝にはなってしまいますが、自分が出したこちらの記事でも解説しているので興味が出たら読んでみてください。
基礎は身につけている前提の記事です。基礎はざっくり省いているのでよろしくお願いします。
本編
まず、カスタムコンポーネントの大まかな基礎。
コンポーネント付ける側
カスタムコンポーネントは、Block,Itemにつけられるminecraft:custom_componentsというコンポーネントで指定できます。valueには文字列の配列(コンポーネントの名前の配列)が入ります。
"minecraft:custom_components": [ "コンポーネントの名前", "複数書く場合はこのようにコンマで区切る" ]
バニラのコンポーネントと同じような、“コンポーネント名”: { “プロパティ”: “値” }という書き方はできません。
アイテムのformat_versionは1.21.0以上である必要があります。(1.20.0でもいけるかも?)
ちなみに、1.21.10だとベータAPIを使う必要がないと聞きます。
コンポーネントの機能側
そのコンポーネント自体を追加する処理はScriptAPIに書きます。
以下例。
world.beforeEvents.worldInitialize.subscribe(({ itemComponentRegistry }) => {
itemComponentRegistry.registerCustomComponent(
"mycomponent:on_use", //mycomponent:on_useという名前でコンポーネントを追加
{
onUse({ source }) { //使ったらメッセージ送信
source.sendMessage("used");
},
onMineBlock({ block, source }) { //ブロックを掘ったら爆発
block.dimension.createExplosion(block.location, 2);
source.runCommand("say コマンドも実行できまっせ");
}
}
);
});
…まあ、特に言う事ありませんね。
ここで説明しても仕方がないのでWorldInitializeBeforeEventクラスを説明している場所のリンクでも置いておきます。
コンポーネントを複数追加するときは、itemComponentRegistry.regiaterCistomComponent(…);自体を増やしてあげてください。
変換の例
古い書き方では…
アイテム
{
"format_version": "1.16.100",
"minecraft:item": {
"description": {
"identifier": "test:item"
},
"components": {
"minecraft:on_use": {
"on_use": {
"event": "say_used"
}
}
},
"events": {
"say_used": {
"run_command": {
"command": ["say used"]
}
}
}
}
}
新たな書き方では…
アイテム
{
"format_version": "1.21.10",
"minecraft:item": {
"description": {
"identifier": "test:item"
},
"components": {
"minecraft:custom_components": ["test:say_used"]
}
}
}
ScriptAPI
import { world } from "@minecraft/server";
world.beforeEvents.worldInitialize.subscribe(({ itemComponentRegistry }) => {
itemComponentRegistry.registerCustomComponent(
"test:say_used",
{
onUse({ source }) {
source.sendMessage("used"); //ScriptAPIでの書き方が苦手なときはrunCommandでも可
}
}
);
});
最後に
どうでしょうか。ScriptAPIに慣れていない人にとってはまだ慣れない機能だったかもしれません。
カスタムコンポーネントへの移行ができていない人がよく見られ、その人がevents削除自体知らないということも多いのでこのような記事を書いてみました。役に立てたら嬉しいです。
今回の記事で分からなかった部分があれば、自分が開いているこちらのコミュニティで質問してみてください。コメントでの質問も駄目とは言いませんが長くなるような質問はやる気が尽きる可能性大。
まだ知らないことも少なくないので、間違っているところがあれば教えてほしいです。
それでは良きアドオンライフを~
コメント
ScriptAPIの解説含めてわかりやすかったです!
ありがとうございます!
スクリプトを習い始めた者です。スクリプトを実行してみたのですが ran with error: [syntax error] expecting ‘,’ at main.js:18とエラーがでます。ちなみに構文は以下の通りです。
import { world, system } from “@minecraft/server”;
system.afterEvents.entitySpawn.subscribe(ev => {
const zombie = world.getDimension(“overworld”);
if (typeId === “minecraft:zombie”) {
system.runInterval(() => {
//(Command)
zombie.runCommandAsync(“execute as @e[type=minecraft:zombie] at @s positioned ~-4~~-4 run gametest create test -48 48 -48”);
zombie.runCommandAsync(“execute as @e[type=minecraft:zombie] at @s positioned ~-4~~1 run gametest create test -48 48 48”);
zombie.runCommandAsync(“execute as @e[type=minecraft:zombie] at @s positioned ~1~~1 run gametest create test 48 48 48”);
zombie.runCommandAsync(“execute as @e[type=minecraft:zombie] at @s positioned ~2~~-7 run gametest create test 48 48 -48”);
zombie.runCommandAsync(“execute as @e[type=minecraft:zombie] at @s positioned ~3~~-3 run gametest create test 48 48 -48”);
zombie.runCommandAsync(“execute as @e[type=minecraft:zombie] at @s positioned ~~~-8 run gametest create test 48 48 -48”);
}
}
});
マイクラのバージョンは1.21.30、アドオンのバージョンは1.0.0、format_versionは2、スクリプトのserverのmoduleのバージョンは1.13.0、マニフェストのmin_engine_versionは1.21.20にしています。間違えているところをご指摘いただけると幸いです。よろしくお願いします。
※上のスクリプトの構文の空白の部分がコメントをしたときになくなっていますが、ちゃんと空白も入れています。
コメントありがとうございます。
1. SystemのafterEventsにentitySpawnというプロパティはありません。entitySpawnがあるのはWorldのafterEventsです。なので、systemをworldに変えてください。
2. ifのところで、typeIdが取得できていません。これではtypeIdには常にundefinedが入ってしまっているので、ev.entity.typeIdとしてEntitySpawnAfterEventのentityプロパティのtypeIdプロパティの値を取得してあげてください。
3. system.runIntervalで、括弧が足りていません。system.runInterval(() => {})で1つの塊であるのに対し、このコードでは(() => {で終わっており関数を実行できていません。
自分が確認できるのはこの3つですね。
scriptapiを勉強してくれる人が居るのはとても嬉しい…応援しています!
餅わらびすとさんにご指摘いただいたところを修正し、再度スクリプトを実行してみたら、無事スクリプトを実行できました!対応が早く、分かりやすく説明してくださったおかげでとても助かりました!ありがとうございます!今後も頑張ります!