はじめに
BEのアドオン開発を書いたjavascript周りの記事がなかなか見つかりづらかった&ドキュメント見ても書いてないものがあったので備忘録として記載
Minecraft Bedrock Edition 1.20.30 windows版
主な対象
javascriptやったことあるよ
やったことないけど他の言語やってなんとなく読めるよ
準備
minecraftのアドオンが置かれるフォルダを探す
隠しフォルダになってるAppDataの更に下にある
%localappdata%\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang\
↑をWin+R押して貼り付けるのが楽
development_behavior_packsに新規フォルダを作成
このフォルダ名は表に出てこないのでなんでも良いが、大量にアドオン作った場合わかりにくくなるので認識しやすい名前にした方が良い
とりあえずsampleフォルダを作成
com.mojans
┗development_behavior_packs
┗sample
manifest.json
これが無いとまず認識してくれない
先程作ったsampleフォルダ内にmanifest.jsonを作成
com.mojans
┗development_behavior_packs
┗sample
┗manifest.json
manifest.jsonの中身を書く
{
"format_version": 2,
"header": {
"name": "TNT",
"description": "足元がTNTになる",
"uuid": "【ここにUUID取ってきて入れる】",
"version": [1,0,0],
"min_engine_version": [1,16,0]
},
"modules": [
{
"type": "script",
"version": [1,0,0],
"uuid": "【ここにUUID取ってきて入れる】",
"entry": "scripts/main.js"
}
],
"dependencies": [
{
"module_name": "@minecraft/server",
"version": "1.5.0"
}
]
}
読み込まれた際にnameとdescriptionがそれぞれこんな感じになる
2箇所のuuidはそれぞれUUIDジェネレーターで取ってきた値を入れる
私は面倒なのでVSCodeのUUID Generatorという拡張機能で入れてます
modulesの書き方について書いてある記事が少なく見つけづらかった部分
type
scriptを指定 modules内で複数書く時にdataなら問題ないがものによっては競合するみたいな記載をどこかで見た 今回はmodules内が1個だけなので気にしない
entry
jsファイルが置いてあるとこを記載 上ではscripts/main.jsとあるがこれから作る
javascriptファイルを作成
manifest.jsonのentryで記載した通りにscriptsフォルダとmain.jsを作成
com.mojans
┗development_behavior_packs
┗sample
┣manifest.json
┗scripts
┗main.js
ここまで用意すればゲームで該当のビヘイビアーパックを指定することで読み込みまでしてくれる
チート使用をオンにしておけばjsファイルを更新した際に/reloadで再読込してくれる
main.js内にプログラムを書く
import { world, system } from "@minecraft/server"
const INTERVAL_SEC = 1 //インターバルで1秒毎に呼ぶ
system.runInterval(() => {
// 全プレイヤー情報を取得
const players = world.getAllPlayers()
// 全プレイヤーに対し処理を実行
for (const player of players) {
//playerの座標を取得
let loc = player.location
//y座標をプレイヤーの1つ下にセット
loc.y = loc.y - 1
// 現在の世界情報を取得 minecraft:overworld or minecraft:nether or minecraft:the_end
let dimension = player.dimension.id
// 足元のブロックをTNTに置換
world.getDimension(dimension).runCommand(`setblock ${loc.x} ${loc.y} ${loc.z} minecraft:tnt`)
}
}, INTERVAL_SEC * 20)
system.runInterval(func,tickInterval)
https://learn.microsoft.com/en-us/minecraft/creator/scriptapi/minecraft/server/system#runinterval
javascriptのsetIntervalと基本的に同じものですが、第二引数の値はミリ秒ではなくminecraftで使用される tick(0.05秒)単位なので秒数にしたい場合は×20する
あんまり頻度が高いとswitchやスマホ勢がカクつく影響あり
windows版でも1秒インターバルでジャンプブリッジして落ちた例あり
world.getAllPlayers()
https://learn.microsoft.com/en-us/minecraft/creator/scriptapi/minecraft/server/world#getplayers
全プレイヤー情報を取得
player.location
https://learn.microsoft.com/en-us/minecraft/creator/scriptapi/minecraft/server/player#properties
playerクラスのプロパティに書いてないけど座標情報持ってないはずはないと思って取りにいったらあった このあたり公式ドキュメントが優しくない
Entityクラスを拡張してPlayerが作られているのを見落としてました
↓のplayer.dimension.idも同様
player.dimension.id
minecraft:overworldやらminecraft:netherやらminecraft:the_endを返してくる
どのディメンション+座標のセットにしないとネザー行ってもオーバーワールド側変更しちゃってあれ?みたいになる
world.getDimension(dimension).runCommand(command)
dimensionのワールドでコマンド実行する
クリエイティブをあまりやらないのでわからないがそういうコマンドとか使える 実行者はサーバーなので近い人みたいな相対的になるオプションは使えない・・・と思う(試してない)
おまけ備忘録
https://learn.microsoft.com/en-us/minecraft/creator/scriptapi/minecraft/server/playerspawnafterevent
PlayerSpawnAfterEventクラスがあってもどう使うかわからなかった
BEアドオン開発のdiscordまで見に行ってやっと理解
HogeFugaBeforeEventクラス/HogeFugaAfterEventクラスがあったらイベント登録方法は
【world】の【afterEvent/beforeEvent】の【afterEvent/beforeEventを抜いてキャメルケースにしたクラス名】をsubscribeする
import { world } from "@minecraft/server"
world.afterEvent.hogeFuga.subscribe(event => {
//処理
})
world.beforeEvent.hogeFuga.subscribe(event => {
//処理
})
なんじゃそりゃって感じではあるがイベントリスナー登録はこれで解決した