API

モブ

カスタムモブは、ゲーム内のモブの体(モデル、アニメーション、大きさ、移動の仕方)を使い、その上にあなたのテクスチャを塗り、あなたのステータス、行動、ドロップを組み合わせたものです。他のコンテンツと同じく、プロパティの一覧として宣言します。

モブを宣言する

content/creatures.craftCraftScript
creature "ghost" {
    body: "minecraft:zombie"
    texture: "entity/ghost"
    health: 40
    speed: 0.3
    attack: 4
    behaviour: ["swim", "melee_attack", { wander: 0.8 }, { look_at_players: 10 }, "look_around"]
    targets: ["hurt_by", "minecraft:pig"]
    loot: [ { item: "ghostmod:ecto", count: [1, 2] } ]
}
プロパティ 値 デフォルト
body ゲーム内のモブの id:minecraft:zombie、minecraft:wolf、minecraft:cow… 必須
texture 体のモデルの上に塗るテクスチャのパス:entity/ghost は Mod の textures/entity/ghost.png 体の見た目
model 独自の 3D モデル:entity/robot は Mod の models/entity/robot.json(下記) 体のモデル
size ブロック単位の [width, height]:当たり判定と、クリックされる範囲(下記) 体のもの
health 体力 体のもの
speed 歩く速さ(ゾンビは 0.23、オオカミは 0.3) 体のもの
attack 近接攻撃のダメージ 体のもの
follow_range 何ブロック先までターゲットを検知するか 体のもの
behaviour 重要なものから順に並べた行動の一覧(下記) 体の行動
targets 優先度順に、誰を攻撃するか(下記) なし
loot [{ item, count, chance }, …]。ブロックと同じく、各アイテムは個別に抽選されます なし
spawns 自然に現れるバイオーム。重みとグループの人数つき(下記) 自然にはスポーンしない
breed_item 2 体を繁殖させるアイテム(下記) 繁殖しない
tame_item 手なずけるアイテム(下記) 手なずけられない
rideable true にするとプレイヤーが乗れる(下記) false

行動

一覧の順番が優先度です。2 つが同時に動こうとしたときは、先にあるほうが優先されます。それぞれ、名前だけ、主な設定を指定する { name: number }、またはすべての設定を持つマップで書きます。

行動 内容 設定
"swim" 水中で浮かんでいる。
"look_around" 何もしていないときに辺りを見回す。
"wander"、{ wander: 0.8 } うろうろ歩き回る。 speed、デフォルト 1
"look_at_players"、{ look_at_players: 10 } 近くのプレイヤーを見る。 range(ブロック)、デフォルト 8
"melee_attack"、{ melee_attack: 1.2 } ターゲットを追いかけて殴る。 speed、デフォルト 1
"panic"、{ panic: 1.5 } ダメージを受けると逃げる。 speed、デフォルト 1.25
{ avoid: "minecraft:wolf", distance: 8, speed: 1.2 } そのモブから距離を取る。 distance(ブロック)、speed
{ follow: "minecraft:wheat", speed: 1 } そのアイテムを持っている人についていく。 speed
{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 } ターゲットに向かって飛び道具を撃ちます(下記)。 projectile, interval, range, speed, power, damage
"breed", { breed: 1 } エサを与えられると、同じ種類の相手と繁殖します。 speed
"follow_parent", { follow_parent: 1.1 } 子どもは親のそばにいます。 speed
{ follow_owner: 1.2, distance: 8 } 手なずけられたモブは飼い主についていきます。 speed、distance(ブロック数)
{ fly_around: 1 } 飛び回ります。飛ぶ体(オウム、ミツバチ、アレイ)向け。 speed
{ can_start: …, tick: … } 自分のコード(下記)。 can_start, tick, keep_going, moves

速さの数値は、モブの基本速度に掛けられます。{ wander: 0.8 } は歩く速さより少し遅く歩き回ります。

ターゲット

targets は、優先度の高い順に誰を攻撃するかを指定します。"hurt_by" は自分にダメージを与えた相手、エンティティの id はその種類で最も近いエンティティです(プレイヤーなら "minecraft:player"、ブタなら "minecraft:pig")。実際に攻撃するには、"melee_attack" のような攻撃を行う行動が必要です。

スポーンさせる

commands/haunt.craftCraftScript
command haunt requires "ghostmod.haunt" describe "今いる場所に幽霊を召喚する" {
    if player == null { return "プレイヤー専用です" }
    world().spawn("ghostmod:ghost", player.location)
    return "&7幽霊が現れた…"
}

id はあなたの Mod のもの:ghostmod:ghost です。ゲームのコマンド /summon ghostmod:ghost も使えます。

自然にスポーンさせる

spawns を追加すると、ゲーム本来のモブと同じように、モブがワールドに自然に現れます。

content/ghost.craftCraftScript
creature "ghost" {
    body: "minecraft:zombie"
    spawns: [ { biomes: ["minecraft:dark_forest", "#minecraft:is_forest"], weight: 20, group: [1, 2] } ]
}

各エントリには、現れる biomes(ID、またはバイオームのグループ全体を指す #タグ)、weight(重み:そのバイオームの他のモブと比べた頻度。牛は 8、ゾンビは 95)、そして group の人数の範囲を指定します。

ベースにした体のスポーン条件に従います。ゾンビの体なら暗い場所に、牛の体なら明るい草地に現れます。これはワールド生成時にも、その後も同じです。

スポーンエッグ。 すべてのモブには、そのモブの ID に _spawn_egg を付けたスポーンエッグ(ghost_spawn_egg)が、クリエイティブのスポーンエッグタブに追加されます。テクスチャは、Mod に textures/item/ghost_spawn_egg.png があればそれを使い、なければ体のスポーンエッグと同じ見た目になります。

Kotlin では:

content/Creatures.ktKotlin
content.creature("ghost") {
    body = "minecraft:zombie"
    spawn("minecraft:dark_forest", "#minecraft:is_forest", weight = 20, group = 1..2)
}

コードからモブを操る

宣言したモブも、その他のモブも Creature です。イベント、コマンド、タイマーから命令を出せます。

メンバー 役割
target 攻撃している相手。読み取りも設定もできます。
moveTo(location, speed), move_to 指定した位置まで歩きます。speed は通常の速度に掛ける倍率です。
stop() 歩くのをやめます。
isMoving, is_moving どこかへ向かって歩いているか。
lookAt(location), look_at 指定した位置のほうを向きます。
canSee(entity), can_see そのエンティティが視線の通る位置にいるか。
isBaby 子どもかどうか。
ownerId 手なずけた後の、飼い主の ID。
tame(player) そのプレイヤーを飼い主にします。
isSitting 座っているかどうか。
playAnimation(name), play_animation モデルのアニメーションを 1 つ再生します(下記参照)。

すべてのエンティティには velocity(1 ティックあたりのブロック数で表す Vector)があります。読み取ったり設定したりして押し出せます。entity.velocity = vector(0, 0.6, 0) で上に打ち上げます。

CraftScript では、型を付けた let でエンティティをモブに絞り込めます。実行時に検査されます。

commands/pup.craftCraftScript
command pup requires "dogmod.pup" describe "Get a pet dog" {
    if player == null { return "Players only" }
    let dog: Creature = world().spawn("dogmod:dog", player.location)
    dog.tame(player)
    dog.look_at(player.location)
    dog.velocity = vector(0, 0.6, 0)      // a little hop
    return "&7Good dog!"
}

独自の行動

用意された行動で足りないときは、自分のコードで書けます。他の行動と同じく behaviour のリストに入れ、その位置が優先度になります。

content/herder.craftCraftScript
creature "herder" {
    body: "minecraft:wolf"
    targets: ["minecraft:pig"]
    behaviour: [
        "swim",
        {
            can_start: fun(c) { return c.target != null && c.can_see(c.target) },
            tick: fun(c) {
                if c.target != null {
                    c.look_at(c.target.location)
                    if !c.is_moving { c.move_to(c.target.location, 1.2) }
                }
            }
        },
        { wander: 1 }
    ]
}
  • can_start:数ティックごとに呼ばれます。始めるべきかどうかを返します。
  • tick:行動が有効な間、毎ティック実行されます。
  • keep_going:続けるかどうかを返します。省略すると can_start と同じです。
  • moves:既定は true。動く行動は、動く別の行動と同時には実行されません。リストで前にあるほうが優先されます。見る・反応するだけの行動には false を使います。

Kotlin では: Behaviour.Custom(canStart = { … }, tick = { … }, keepGoing = …, moves = true)

動物:繁殖、手なずけ、騎乗、飛行

いくつかのプロパティと行動で、モブを動物にできます。これはリンゴで繁殖し、骨で手なずけられ、乗ることもできます。

content/mooble.craftCraftScript
creature "mooble" {
    body: "minecraft:cow"
    tame_item: "minecraft:bone"
    breed_item: "minecraft:apple"
    rideable: true
    behaviour: ["swim", { breed: 1 }, { follow_parent: 1.1 }, { follow_owner: 1.2, distance: 8 }, { wander: 0.8 }]
}
  • 繁殖。 breed_item と行動 "breed":そのアイテムを与えると、同じ種類の 2 体がその種類の子どもを産みます。動物の体(牛、オオカミ、ニワトリなど)が必要です。子どもは "follow_parent" で親のそばにいます。
  • 手なずけ。 tame_item:試行 3 回に 1 回成功します。飼い主は記憶され、手なずけたモブは飼い主を決してターゲットにしません。スニークして素手で使うと、座ったり立ち上がったりします。{ follow_owner: 1.2, distance: 8 } で飼い主についていきます。
  • 騎乗。 rideable: true:素手で使うと乗れます(手なずけた後は飼い主だけ)。移動キーとマウスで操縦し、スニークで降ります。
  • 飛行。 飛ぶ体(オウム、ミツバチ、アレイ)には { fly_around: 1 }。rideable な飛ぶ体のモブは、乗っている人が上を向くと上昇し、下を向くと急降下します。

Kotlin では:breedItem = …、tameItem = …、rideable = true、そして行動 Behaviour.Breed()、Behaviour.FollowParent()、Behaviour.FollowOwner(speed, distance)、Behaviour.FlyAround()。

独自の飛び道具

ゲーム内の飛び道具のほかに、Mod が独自の飛び道具を宣言できます。ダメージ、重力、着弾したときの処理を自由に決められます。

content/frost_bolt.craftCraftScript
projectile "frost_bolt" {
    damage: 4
    gravity: false
    on_hit: fun(e) {
        let at = e.entity?.location ?? e.block?.location
        if at != null { e.projectile.world.spawn_particle("minecraft:snowflake", at.add(0.5, 1, 0.5), 12, 0.4, 0.02) }
    }
}
  • damage:当たった相手に与えるダメージ。
  • gravity:false にすると直線に飛びます。
  • on_hit:fun(e)。着弾したときに呼ばれ、hit イベントと同じ e を受け取ります:e.projectile、e.shooter、そして e.entity または e.block。
  • texture:飛び道具はそのアイテムの見た目で飛ぶので、既定では textures/item/<id>.png を使います。別のものを使うには texture を指定します。

他の飛び道具と同じように使えます:world.shoot("mymod:frost_bolt", from, velocity, shooter)、モブでは { ranged_attack: "mymod:frost_bolt" }。Kotlin では:

content/FrostBolt.ktKotlin
content.projectile("frost_bolt") {
    damage = 4.0
    gravity = false
    onHit = { e -> /* … */ }
}

遠距離攻撃と飛び道具

行動 ranged_attack でモブが撃つようになります。ターゲットが射程内で視界に入るまで近づき、そこで撃ちます。

content/frost_spirit.craftCraftScript
creature "frost_spirit" {
    body: "minecraft:snow_golem"
    behaviour: [{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 }, { wander: 0.6 }]
    targets: ["minecraft:zombie", "hurt_by"]
}

on hit(e) {
    if e.shooter?.type == "frostmod:frost_spirit" && e.entity != null {
        e.entity.velocity = vector(0, 0.2, 0)      // knocked up
    }
}
設定 意味
ranged_attack ranged_attack:飛び道具(minecraft:arrow、minecraft:snowball、minecraft:small_fireball、minecraft:wind_charge など)。
interval interval:発射の間隔(ティック)。
range range:撃ち始める距離(ブロック)。
speed speed:近づくときの歩く速さ。
power power:飛び道具の飛ぶ速さ。
damage damage:命中時の追加ダメージ。

コードから撃つには(モブでもプレイヤーのアビリティでも)、world().shoot(projectile, from, velocity, shooter, damage) を使います。

Kotlin では:

content/FrostSpirit.ktKotlin
creature("frost_spirit") {
    body = "minecraft:snow_golem"
    behaviour(Behaviour.RangedAttack(Identifier.parse("minecraft:snowball"), interval = 20, range = 14.0, damage = 3.0))
    target(TargetRule.Nearest(Identifier.parse("minecraft:zombie")))
}

// From code, e.g. a player's ability:
world.shoot(Identifier.parse("minecraft:small_fireball"), from, Vector(0.0, 0.0, 1.5), shooter = player, damage = 4.0)

hit イベント(ProjectileHitEvent)は、飛び道具が当たったときに発生します。e.projectile、e.shooter、そして当たった対象に応じて e.entity か e.block が使えます。キャンセルすると飛び道具は通り抜けます。イベントを参照してください。

知っておくと良いこと

  • **体ごとに限界があります。**ゲーム内のモブには、持っていないステータスがあるものもあります。たとえばウシには攻撃力がありません。設定しても無視され、Crafting がログに警告を出します。
  • **歩かない体。**自分で経路を探せない体は、歩く行動(うろつき、追跡、逃走、追従、回避)を無視します。それ以外は動きます。
  • **behaviour がなければ、**モブは使っている体と同じように振る舞います。一覧を書いた時点で、そこにあることしかしなくなります。
  • **モデルは見た目だけを変えます。**動きと行動は常に体のもので、大きさも size を指定しない限り体のものです。
  • カスタムモブは他と同じ生きたエンティティです。spawn、damage、entity_death イベントを受け取り、data を持ち、ワールドとプレイヤーにあるもので操作できます。

Kotlin では

content/Creatures.ktKotlin
package com.example.rubies.content

object Creatures {
    fun register(content: ContentBuilder) {
        content.creature("ruby_golem") {
            body = "minecraft:zombie"
            texture = "entity/ruby_golem"
            health = 60.0
            speed = 0.25
            attackDamage = 6.0
            behaviour(Behaviour.Swim)
            behaviour(Behaviour.MeleeAttack())
            behaviour(Behaviour.Wander(0.6))
            behaviour(Behaviour.LookAtPlayers(12f))
            behaviour(Behaviour.LookAround)
            target(TargetRule.HurtBy)
            target(TargetRule.Nearest(Identifier.parse("minecraft:player")))
            drop(Items.RUBY, 2..4)
        }
    }
}

行動:Behaviour.Swim、LookAround、Wander(speed)、LookAtPlayers(range)、MeleeAttack(speed)、Panic(speed)、Avoid(entity, distance, speed)、Follow(item, speed)。ターゲット:TargetRule.HurtBy と TargetRule.Nearest(id)。ドロップはブロックと同じく drop(item, count, chance) で追加します。

独自の 3D モデル

model を追加すると、モブは体のモデルの代わりにあなたのモデルで描画されます。大きさ、動き、行動は引き続き体のものを使い、モデルが変えるのは見た目だけです。

content/robot.craftCraftScript
creature "robot" {
    body: "minecraft:pig"
    model: "entity/robot"
    texture: "entity/robot"
    behaviour: ["swim", { wander: 0.8 }, { look_at_players: 10 }]
}

モデルは Mod の models/entity/robot.json、そのテクスチャは textures/entity/robot.png です。Kotlin では:creature("robot") { body = "minecraft:pig"; model = "entity/robot"; texture = "entity/robot" }。形式はゲームのバージョンが変わっても同じです。

models/entity/robot.jsonJSON
{ "texture_size": [64, 64],
  "bones": [
    { "name": "body", "pivot": [0, 6, 0], "cubes": [ { "origin": [-5, 6, -3], "size": [10, 10, 6], "uv": [0, 0] } ] },
    { "name": "head", "parent": "body", "pivot": [0, 16, 0], "cubes": [ { "origin": [-4, 16, -4], "size": [8, 8, 8], "uv": [0, 16] } ] },
    { "name": "left_leg", "pivot": [2.5, 6, 0], "cubes": [ { "origin": [1, 0, -1.5], "size": [3, 6, 3], "uv": [32, 0] } ] },
    { "name": "right_leg", "pivot": [-2.5, 6, 0], "cubes": [ { "origin": [-4, 0, -1.5], "size": [3, 6, 3], "uv": [32, 16] } ] }
  ],
  "animations": { "head": "look", "left_leg": "walk", "right_leg": "walk_opposite", "body": "idle" } }

大きさはピクセル単位(16 がブロック 1 つ分)で、y はモブの足元から上向きです。

  • ボーン:name、省略可能な parent(一緒に動く)、pivot(回転の中心点)、cubes。
  • キューブ:origin(最も低い角)、size、uv(画像上でテクスチャが始まる位置)。レイアウトは通常のボックス展開です。幅 w、高さ h、奥行き d のキューブは、2(w+d) × (d+h) ピクセルの領域を使います。
  • アニメーションはボーンごとに、名前または名前の一覧で指定します:
アニメーション 内容
look モブが見ている方向に向く。頭用。
walk、walk_opposite 歩くときに揺れる。後者は逆位相で、反対側の手足用。
idle わずかな揺れ。
spin 回り続ける。

モデルを描画できない場合、モブは体の見た目になり、ログに理由が出力されます。

大きさ

モブの大きさは体と同じです。モデルがそれより小さい、または大きいときは、size: [width, height] をブロック単位で指定して、当たり判定とクリックされる範囲をプレイヤーに見える姿に合わせます。

content/drake.craftCraftScript
creature "drake" {
    body: "minecraft:bee"
    model: "entity/drake"
    texture: "entity/drake"
    size: [1.4, 1.1]
}

Kotlin では:size = 1.4 to 1.1。

キーフレームアニメーション

用意されたアニメーション以上の動きには、bones と animations の隣に clips セクションを追加します。

models/entity/robot.jsonJSON
{ "bones": [ … ],
  "animations": { … },
  "clips": {
    "idle": { "length": 2.0, "bones": { "head": { "position": { "0": [0, 0, 0], "1": [0, 0.6, 0], "2": [0, 0, 0] } } } },
    "walk": { "length": 1.0, "bones": { "body": { "rotation": { "0": [0, 0, -6], "0.5": [0, 0, 6], "1": [0, 0, -6] } } } },
    "roar": { "length": 1.5, "bones": {
      "head": { "rotation": { "0": [0, 0, 0], "0.4": [-35, 0, 0], "1.1": [-35, 0, 0], "1.5": [0, 0, 0] },
                "scale": { "0": 1, "0.4": 1.35, "1.1": 1.35, "1.5": 1 } },
      "body": { "position": { "0": [0, 0, 0], "0.3": [0, 4, 0], "0.6": [0, 0, 0] } } } }
  } }
  • 各クリップには秒単位の length(長さ)があり、ボーンごとに最大 3 つのチャンネルを持てます。rotation(度)、position(ピクセル、y が上)、scale(数値または [x, y, z])です。
  • キーは秒単位の時刻です。キーとキーの間の値は直線的に補間されます。クリップに "interpolation": "smooth" を追加すると、代わりにキーを通る曲線になります。チャンネルはクリップ全体で 1 つの値にすることもできます。
クリップ 再生されるとき
walk 歩いている間、足の動きに合わせてループします。
idle 立ち止まっている間ループします。
attack 攻撃するときに再生されます。
それ以外の名前 コードが求めたときに再生されます:c.play_animation("roar")。Crafting を使っている近くのプレイヤーに見えます。
Smooth clipJSON
"idle": { "length": 1.2, "interpolation": "smooth", "bones": {
  "left_wing": { "rotation": { "0": [0, 0, -20], "0.6": [0, 0, 25], "1.2": [0, 0, -20] } } } }

コードから始めたクリップは、walk、idle、attack を置き換えるのではなく、その上に重ねて再生され、足し合わされます。モブは歩きながら吠えることもできます。

独自のモデルを持つモブの子どもは、半分の大きさで描かれます。

テクスチャ

モデルがない場合、テクスチャのレイアウトは選んだ体(ゾンビ、オオカミ…)と同じなので、その体のテンプレートから始めて上から塗れます。アイテムやブロックのテクスチャと同じく、Mod の中に入れます。

Mod 場所
CraftScript(フォルダー) mods/ghostmod/textures/entity/ghost.png
Kotlin または Java src/main/resources/assets/ghostmod/textures/entity/ghost.png