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 — це textures/entity/ghost.png мода вигляд тіла
model власна 3D-модель: entity/robot — це 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 предмет, від якого дві істоти розмножуються (нижче) не розмножується
tame_item предмет, що її приборкує (нижче) не можна приборкати
rideable true дозволяє гравцям їздити на ній (нижче) false

Поведінки

Порядок у списку — це пріоритет: коли дві поведінки хочуть діяти водночас, перемагає та, що раніше. Записуй кожну як назву, як { 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 належить твоєму моду: 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), на вкладці творчого режиму з яйцями виклику. Його текстура — 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 Іде до вказаної точки. Швидкість множить її звичайну швидкість.
stop() Перестає йти.
isMoving, is_moving Чи йде вона кудись.
lookAt(location), look_at Повертається, щоб подивитися на точку.
canSee(entity), can_see Чи має вона пряму видимість до цієї сутності.
isBaby Чи це дитинча.
ownerId Id її господаря, після приборкання.
tame(player) Робить цього гравця її господарем.
isSitting Чи сидить вона.
playAnimation(name), play_animation Програє одну з анімацій її моделі (див. нижче).

Будь-яка сутність має velocity — 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": нагодовані цим предметом, дві істоти одного виду народжують дитинча цього виду. Потрібне тіло тварини (корова, вовк, курка…). Дитинчата використовують "follow_parent", щоб триматися біля батьків.
  • Приборкання. tame_item: кожна спроба вдається раз із трьох. Господаря запам’ятовують, а приборкана істота ніколи не обирає господаря ціллю. Присядь і використай порожньою рукою, щоб вона сіла або встала. { 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().

Власні снаряди

Окрім снарядів гри, мод може оголошувати власні. У нього своя шкода, своя гравітація і своя дія під час влучання:

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), викликається під час влучання, з тим самим e, що й у події hit: 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 }]
}

Модель — це 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 — це один блок), вісь y спрямована вгору від ніг істоти.

  • Кістка: name, необов’язковий parent (вона рухається разом із ним), pivot (точка, навколо якої вона повертається) і cubes.
  • Куб: origin (його нижній кут), size і uv (де в зображенні починається його текстура). Розкладка звичайна для коробки: куб шириною w, висотою h і глибиною d займає ділянку 2(w+d) на (d+h) пікселів.
  • Анімації задаються для кожної кістки, іменем або списком імен:
Анімація Що робить
look Повертає туди, куди дивиться істота; для голів.
walk, walk_opposite Гойдається під час ходьби; друга — у протифазі, для іншої кінцівки.
idle Легке погойдування.
spin Постійно обертається.
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, а не замість них, і вони додаються: істота може ревіти на ходу.

Якщо модель не вдається намалювати, істота виглядає як її тіло, а журнал пояснює чому.

Розмір

Істота такого самого розміру, як її тіло. Якщо ваша модель менша або більша, задайте 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.

Анімації за ключовими кадрами

Для рухів понад готові анімації додай розділ clips поруч з bones і animations:

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 (довжину) в секундах і, для кожної кістки, до трьох каналів: rotation у градусах, position у пікселях (y вгору) та scale (число або [x, y, z]).
  • Ключі — це моменти часу в секундах. Між ключами значення плавно змінюються по прямій; додайте кліпу "interpolation": "smooth", і він проходитиме через свої ключі по кривій. Канал також може бути одним значенням на весь кліп.
Кліп Коли грає
walk Повторюється, поки вона йде, у такт ногам.
idle Повторюється, поки вона стоїть.
attack Грає в момент удару.
Будь-яка інша назва Грає, коли код попросить: c.play_animation("roar"). Її бачать найближчі гравці з Crafting.

Дитинчата істоти з власною моделлю малюються вдвічі меншими.

Текстури

Без моделі текстура має ту саму розкладку, що й в обраного тіла (зомбі, вовка…), тож можна взяти шаблон для цього тіла й малювати поверх нього. Вона лежить усередині мода, як текстури предметів і блоків:

Мод Де
CraftScript (тека) mods/ghostmod/textures/entity/ghost.png
Kotlin або Java src/main/resources/assets/ghostmod/textures/entity/ghost.png