マケプレ、著書等あったりします!!

マケプレ作品は絶対におススメです!!!!

ScriptAPIで作る、リモコンで見れるテレビ【マインクラフト】

ようこそぷっこ村へ、ししゃもだよ。

(・∀・)ノ

やべー、月一しか更新できてない、何とかしたい。(いつも言ってる)。それはさておき、最近ScriptAPIのカスタムコンポーネントってのが正式リリースされました。いやー、便利すぎるわこれ、マジで何でもできるもん。え?何それ食べれるのって?はい、食べれます。

ざっくりと説明をすると、アイテムやブロックに何かしらのアクションをすることをトリガーにして、自作のScriptを実行することができる機能です。

ブロック置いたらうんこ漏らすとか、アイテム使ったら血尿が出るとかできるようになります。真面目に言うと、統合版では使えないジグソーの代わりに使ったり、今まで試験機能でしか使えなかった、ブロックにインタラクトしたらフォームを表示するとかができます。

色々やってみて、確かな手ごたえみたいなのがあるいい機能なので、軽く備忘録的に情報をまとめてみようかと思います。

インタラクトでテレビをつける

とりあえず、リモコンを持ってテレビをインタラクトすると番組が選択できるようにしてみましょうか。イメージとしてはこんな感じになります↓

ScriptAPIでリモコン使ってテレビ見る【マインクラフト】
ブログの解説用、ScriptAPIを使うとテレビが作れます。ていうかなんでも作れます。「アストロサルガッソー」の宣伝も兼ねた動画だよ。宇宙に行くよ。自動生成だよ。約9割がScriptAPI制御...

大体以下のような感じに書くとなんとかなります。

world.beforeEvents.worldInitialize.subscribe(e => {
  e.blockComponentRegistry.registerCustomComponent('sksp_syamo:astro_tv_show_up', {
    onPlayerInteract(ev : BlockComponentPlayerInteractEvent) {
      const temp_player = ev.player
      // @ts-expect-error
      const main_hand = temp_player?.getComponent("equippable")?.getEquipment("Mainhand")
      if (temp_player === undefined || main_hand === undefined) {return;}
      else if(main_hand.typeId == "sksp_syamo:astro_tv_remocon"){
        Utils.tv_root_form_generator(temp_player)
      }
    }
  });
}

別ファイル
export function tv_root_form_generator(player:Player) {
  player.playSound("effect.tv_on")
  const root_form = new ActionFormData()
    .title({ translate: "text.form_title_1" })
    .body({ translate: "text.form_title_2" })
    .button({ translate: "text.form_title_3" }, "textures/sisyamo_pv/blocks/monitor_astro_tv")
    .button({ translate: "text.form_title_5" }, "textures/sisyamo_pv/gui/tv_button_astro_shopping")
    .button({ translate: "text.form_title_7" }, "textures/sisyamo_pv/misc/logo")
    .button({ translate: "text.form_title_4" }, "textures/sisyamo_pv/gui/tv_button_saving_balance")
    .button({ translate: "text.form_title_6" }, "textures/sisyamo_pv/item/astro_scrap_gear1");
  root_form.show(player).then((r) => {
    if (r.canceled || r.selection === undefined) {return;}
    switch (r.selection) {
      case 0: weather_form_generator(player); break;
      case 1: astro_shopping_form_generator(player); break;
      case 2: astro_facility_form_generator(player); break;
      case 3: savings_balance_form_generator(player); break;
      case 4: game_setting_form(player); break;
    }}).catch((e) => {console.error(e, e.stack);
  });
}

今作ってるアストロサルガッソーからまんま抜いてきてるので、別ファイルとなってますが、これくらいならひとまとめでいいです。恒例の(?)日本語でおkバージョン↓

ワールドが起動準備できた信号を受け取ったら、そのイベント e を引数に実行{
  e にブロックコンポーネント機能として('sksp_syamo:astro_tv_show_up')を登録 {
    プレイヤーがブロックにインタラクトするときのイベントを ev として定義 {
      定数 temp_player に ev の player データを入れる
      定数 main_hand に temp_player の右手にあるアイテムのデータを入れる。ただし何も持ってなかったら undefined とする
      もし temp_player が存在しない、もしくは右手に何も持っていなかったら {ここで終了}
      それ以外でもし temp_player が存在し、右手に "sksp_syamo:astro_tv_remocon" 持っていたら {
         Utils.tv_root_form_generator という関数に temp_player を引き数として渡し実行
      }
    }
  });
}

別ファイル
tv_root_form_generatorという関数を定義(引数はプレイヤー型)
  引数のプレイヤーにeffect.tv_on という音を鳴らす
  テレビの画面をroot_formという定数に定義
    .タイトル(langファイルから取得)
    .本文(langファイルから取得)
    .1個目のボタン(langファイルから取得,画像のアドレス)
    .2個目のボタン(langファイルから取得,画像のアドレス)
    .3個目のボタン(langファイルから取得,画像のアドレス)
    .4個目のボタン(langファイルから取得,画像のアドレス)
    .5個目のボタン(langファイルから取得,画像のアドレス)
  root_formにテレビ画面の押されたボタンのデータ(r)を入れて、引数のプレイヤーに表示する{
    もし (rがキャンセル(右上の×ボタン)が押された または rの中身が未定義なら){ここで終わり}
    それ以外なら以下の処理を r の値と比較して実行 {
      0なら :天気予報 を表示して終わり
      1なら :テレビショッピング を表示して終わり
      2なら :設備投資 を表示して終わり
      3なら :残高照会 を表示して終わり
      4なら :設定画面 を表示して終わり
    }}).なんかエラーがあったら警告だして抜ける
  });
}

以上のようなことをしています。例によって// @ts-expect-errorがありますが、npmを最新にしてもエラー出ます。おそらくマイナーなモジュールなんか一生追いつかないんでしょう、仕方ないね。

注意点、みたいなのは特になくて、ほんとに素直に書いておけば動いてくれるので、今回は割と楽ですね。

ブロックのカスタムコンポーネントを使うと、ストラクチャを入れ子にすることで、街を生成したり、ランダムな確率で宝箱を置いたり、なんてのも簡単にできるようになります。

その辺はまた気が向いたときにでも備忘録を書いてみようかなと思います。

それではこの辺で、お帰りの際はお気をつけて~(・∀・)ノシ

コメント