API
Істоти
Власна істота використовує тіло ігрової істоти (її модель, анімації, розмір і спосіб пересування) з твоєю текстурою поверх, твоїми характеристиками, твоєю поведінкою і твоєю здобиччю. Оголошуєш її, як і решту вмісту: списком властивостей.
Оголоси істоту
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".
Створи її
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, і істота з’являтиметься у світі сама, як істоти самої гри.
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.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 звужує сутність до істоти. Це перевіряється під час виконання:
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 як будь-яка інша, тож її місце — її пріоритет.
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)
Тварини: розведення, приборкання, їзда й політ
Кілька властивостей і поведінок перетворюють істоту на тварину. Ця розмножується з яблуками, приборкується кісткою і на ній можна їздити:
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().
Власні снаряди
Окрім снарядів гри, мод може оголошувати власні. У нього своя шкода, своя гравітація і своя дія під час влучання:
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.projectile("frost_bolt") {
damage = 4.0
gravity = false
onHit = { e -> /* … */ }
}Дальні атаки та снаряди
Поведінка ranged_attack змушує істоту стріляти. Вона наближається, доки ціль не опиниться в зоні дії та в полі зору, і стріляє.
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:
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
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, і істота малюється твоєю моделлю замість моделі тіла. Тіло, як і раніше, задає її розмір, рух і поведінку; модель змінює лише вигляд.
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" }. Формат однаковий у всіх версіях гри.
{ "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 |
Постійно обертається. |
"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] у блоках, щоб те, з чим вона стикається, і те, куди по ній клацають, збігалося з тим, що бачать гравці:
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:
{ "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 |