API
Criaturas
Uma criatura personalizada usa o corpo de uma criatura do jogo (o modelo, as animações, o tamanho e o jeito de se mover) com a sua textura pintada por cima, seus atributos, seu comportamento e seu loot. Você a declara como o resto do conteúdo: uma lista de propriedades.
Declare uma criatura
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] } ]
}| Propriedade | Valores | Padrão |
|---|---|---|
body |
id de uma criatura do jogo: minecraft:zombie, minecraft:wolf, minecraft:cow… |
obrigatório |
texture |
caminho da textura, pintada sobre o modelo do corpo: entity/ghost é o textures/entity/ghost.png do mod |
a aparência do corpo |
model |
seu próprio modelo 3D: entity/robot é o models/entity/robot.json do mod (abaixo) |
o modelo do corpo |
size |
[width, height] em blocos: com o que colide e onde se clica nela (abaixo) |
o do corpo |
health |
pontos de vida | os do corpo |
speed |
velocidade ao andar (um zumbi anda a 0.23, um lobo a 0.3) | a do corpo |
attack |
dano de ataque corpo a corpo | o do corpo |
follow_range |
a quantos blocos de distância ela detecta seus alvos | o do corpo |
behaviour |
lista de comportamentos, do mais ao menos importante (abaixo) | o comportamento do corpo |
targets |
quem ela ataca, em ordem de prioridade (abaixo) | ninguém |
loot |
[{ item, count, chance }, …], igual aos blocos: cada item é sorteado separadamente |
nada |
spawns |
biomas onde surge sozinha, com peso e tamanho do grupo (abaixo) | não surge sozinha |
breed_item |
item que faz duas delas se reproduzirem (abaixo) | não se reproduz |
tame_item |
item que a domestica (abaixo) | não pode ser domesticada |
rideable |
true permite que jogadores a montem (abaixo) |
false |
Comportamentos
A lista é a prioridade: quando dois querem agir ao mesmo tempo, vence o que vem antes. Escreva cada um como um nome, como { nome: número } para o ajuste principal, ou como um mapa com todos os ajustes.
| Comportamento | O que faz | Ajustes |
|---|---|---|
"swim" |
Fica flutuando na água. | |
"look_around" |
Olha em volta quando está parada. | |
"wander", { wander: 0.8 } |
Anda sem rumo. | speed, padrão 1 |
"look_at_players", { look_at_players: 10 } |
Olha para os jogadores próximos. | range em blocos, padrão 8 |
"melee_attack", { melee_attack: 1.2 } |
Persegue e bate no alvo. | speed, padrão 1 |
"panic", { panic: 1.5 } |
Foge quando leva dano. | speed, padrão 1.25 |
{ avoid: "minecraft:wolf", distance: 8, speed: 1.2 } |
Mantém distância dessa criatura. | distance em blocos, speed |
{ follow: "minecraft:wheat", speed: 1 } |
Segue quem estiver segurando esse item. | speed |
{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 } |
Atira um projétil no alvo (abaixo). | projectile, interval, range, speed, power, damage |
"breed", { breed: 1 } |
Se reproduz com outra da sua espécie depois de alimentada. | speed |
"follow_parent", { follow_parent: 1.1 } |
Um filhote fica perto do pai ou da mãe. | speed |
{ follow_owner: 1.2, distance: 8 } |
Uma criatura domesticada segue o dono. | speed, distance em blocos |
{ fly_around: 1 } |
Voa por aí; para corpos voadores (papagaio, abelha, allay). | speed |
{ can_start: …, tick: … } |
Seu próprio código (abaixo). | can_start, tick, keep_going, moves |
Os números de velocidade multiplicam a velocidade base da criatura: { wander: 0.8 } anda sem rumo um pouco mais devagar do que caminha.
Alvos
targets diz quem ela ataca, da maior para a menor prioridade. "hurt_by" é quem causa dano a ela; um id de entidade é a entidade mais próxima desse tipo ("minecraft:player" para jogadores, "minecraft:pig" para porcos). Para o ataque acontecer, a criatura precisa de um comportamento que o execute, como "melee_attack".
Faça-a surgir
command haunt requires "ghostmod.haunt" describe "Invoca um fantasma onde você está" {
if player == null { return "Apenas jogadores" }
world().spawn("ghostmod:ghost", player.location)
return "&7Um fantasma aparece…"
}O id é do seu mod: ghostmod:ghost. O comando do jogo /summon ghostmod:ghost também funciona.
Surgir sozinhas
Adicione spawns e a criatura aparece sozinha no mundo, como as criaturas do próprio jogo.
creature "ghost" {
body: "minecraft:zombie"
spawns: [ { biomes: ["minecraft:dark_forest", "#minecraft:is_forest"], weight: 20, group: [1, 2] } ]
}Cada entrada lista os biomes onde ela surge (um id, ou uma #tag para um grupo inteiro de biomas), um weight (peso: a frequência, em comparação com as outras criaturas desse bioma; uma vaca tem 8, um zumbi 95) e um intervalo de tamanho de group (grupo).
Ela segue as regras de surgimento do seu corpo: com corpo de zumbi surge no escuro, com corpo de vaca na grama, com luz. Vale tanto quando o mundo é gerado quanto depois.
Ovo de geração. Toda criatura também recebe um ovo de geração, seu id mais _spawn_egg (ghost_spawn_egg), na aba criativa de ovos de geração. A textura é textures/item/ghost_spawn_egg.png do mod, se existir; senão, ele tem a aparência do ovo do seu corpo.
Em Kotlin:
content.creature("ghost") {
body = "minecraft:zombie"
spawn("minecraft:dark_forest", "#minecraft:is_forest", weight = 20, group = 1..2)
}Controlar uma criatura pelo código
As criaturas que você declara, e qualquer outro mob, são uma Creature. De um evento, um comando ou um timer você pode dar ordens a elas:
| Membro | O que faz |
|---|---|
target |
Quem ela está atacando. Pode ser lido e definido. |
moveTo(location, speed), move_to |
Anda até uma posição. A velocidade multiplica a velocidade normal. |
stop() |
Para de andar. |
isMoving, is_moving |
Se está indo para algum lugar. |
lookAt(location), look_at |
Vira para olhar uma posição. |
canSee(entity), can_see |
Se tem linha de visão livre até essa entidade. |
isBaby |
Se é um filhote. |
ownerId |
O id do dono, depois de domesticada. |
tame(player) |
Faz desse jogador o seu dono. |
isSitting |
Se está sentada. |
playAnimation(name), play_animation |
Toca uma das animações do seu modelo (veja abaixo). |
Toda entidade tem uma velocity, um Vector em blocos por tick. Leia ou defina para empurrar a entidade: entity.velocity = vector(0, 0.6, 0) a lança para cima.
Em CraftScript, um let com tipo restringe uma entidade a uma criatura. Isso é verificado ao executar:
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!"
}Comportamentos próprios
Quando os prontos não bastam, escreva um com seu próprio código. Ele entra na lista behaviour como qualquer outro, então sua posição é sua prioridade.
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: consultado a cada poucos ticks; devolva se deve começar.tick: roda a cada tick enquanto o comportamento está ativo.keep_going: diz se deve continuar. Se omitido, é igual acan_start.moves:truepor padrão. Um comportamento que se move não roda junto com outro que também se move; vence o que vem antes na lista. Usefalsepara os que só olham ou reagem.
Em Kotlin: Behaviour.Custom(canStart = { … }, tick = { … }, keepGoing = …, moves = true)
Animais: criar, domesticar, montar e voar
Algumas propriedades e comportamentos transformam uma criatura em animal. Esta se reproduz com maçãs, é domesticada com um osso e pode ser montada:
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 }]
}- Criar.
breed_itemmais o comportamento"breed": alimentadas com esse item, duas da mesma espécie geram um filhote dessa espécie. Exige um corpo de animal (vaca, lobo, galinha…). Filhotes usam"follow_parent"para ficar perto dos pais. - Domesticar.
tame_item: cada tentativa funciona uma vez em três. O dono é lembrado, e uma criatura domesticada nunca ataca o dono. Agache e use com a mão vazia para ela sentar ou levantar.{ follow_owner: 1.2, distance: 8 }faz com que siga o dono. - Montar.
rideable: true: use com a mão vazia para subir (depois de domesticada, só o dono). Ela é guiada com as teclas de movimento e o mouse; agache para descer. - Voar.
{ fly_around: 1 }para corpos voadores (papagaio, abelha, allay). Uma criaturarideablecom corpo voador sobe quando quem a monta olha para cima e mergulha quando olha para baixo.
Em Kotlin: breedItem = …, tameItem = …, rideable = true e os comportamentos Behaviour.Breed(), Behaviour.FollowParent(), Behaviour.FollowOwner(speed, distance) e Behaviour.FlyAround().
Projéteis próprios
Além dos projéteis do jogo, um mod pode declarar os seus. Ele tem dano, gravidade e efeito ao cair próprios:
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: dano causado a quem ele atinge.gravity:falsefaz com que voe em linha reta.on_hit:fun(e), chamado quando ele cai, com o mesmoedo eventohit:e.projectile,e.shooteree.entityoue.block.texture: o projétil voa com a aparência do seu item, então por padrão usatextures/item/<id>.png; definatexturepara usar outra.
Use-o como qualquer outro projétil: world.shoot("mymod:frost_bolt", from, velocity, shooter), ou, em uma criatura, { ranged_attack: "mymod:frost_bolt" }. Em Kotlin:
content.projectile("frost_bolt") {
damage = 4.0
gravity = false
onHit = { e -> /* … */ }
}Ataques à distância e projéteis
O comportamento ranged_attack faz uma criatura atirar. Ela se aproxima até o alvo estar ao alcance e à vista, e então dispara.
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
}
}| Ajuste | Significado |
|---|---|
ranged_attack |
ranged_attack: o projétil (minecraft:arrow, minecraft:snowball, minecraft:small_fireball, minecraft:wind_charge…). |
interval |
interval: ticks entre os disparos. |
range |
range: distância em blocos a partir da qual atira. |
speed |
speed: velocidade ao andar enquanto se aproxima. |
power |
power: a velocidade com que o projétil voa. |
damage |
damage: dano extra ao acertar. |
Para atirar pelo código, com criaturas ou com a habilidade de um jogador, use world().shoot(projectile, from, velocity, shooter, damage).
Em 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)O evento hit (ProjectileHitEvent) dispara quando um projétil atinge algo. Ele tem e.projectile, e.shooter e e.entity ou e.block, conforme o que foi atingido. Cancele e o projétil atravessa. Veja Eventos.
Bom saber
- Cada corpo tem seus limites. Algumas criaturas do jogo não têm certo atributo: uma vaca não tem dano de ataque. Se você o definir, ele é ignorado e o Crafting avisa no log.
- Corpos que não andam. Corpos que não conseguem encontrar um caminho sozinhos ignoram os comportamentos de andar (andar sem rumo, perseguir, fugir, seguir, evitar); o resto funciona.
- Sem
behaviour, a criatura se comporta como o corpo que usa. Assim que você escreve a lista, ela só faz o que está nela. - O modelo só muda o visual. O movimento e o comportamento sempre vêm do corpo, e o tamanho também, a menos que você defina
size. - Uma criatura personalizada é uma entidade viva como qualquer outra: recebe os eventos
spawn,damageeentity_death, temdata, e você a manipula com o que está em O mundo e os jogadores.
Em 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)
}
}
}Comportamentos: Behaviour.Swim, LookAround, Wander(speed), LookAtPlayers(range), MeleeAttack(speed), Panic(speed), Avoid(entity, distance, speed), Follow(item, speed). Alvos: TargetRule.HurtBy e TargetRule.Nearest(id). Adicione loot com drop(item, count, chance), igual aos blocos.
Seu próprio modelo 3D
Adicione model e a criatura é desenhada com o seu modelo em vez do modelo do corpo. O corpo continua dando a ela o tamanho, o movimento e o comportamento; o modelo só muda a aparência.
creature "robot" {
body: "minecraft:pig"
model: "entity/robot"
texture: "entity/robot"
behaviour: ["swim", { wander: 0.8 }, { look_at_players: 10 }]
}O modelo é o models/entity/robot.json do mod e a textura dele é textures/entity/robot.png. Em Kotlin: creature("robot") { body = "minecraft:pig"; model = "entity/robot"; texture = "entity/robot" }. O formato é o mesmo em todas as versões do jogo.
{ "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" } }As medidas são em pixels (16 é um bloco), com y apontando para cima a partir dos pés da criatura.
- Osso:
name, umparentopcional (ele se move junto),pivot(o ponto em torno do qual gira) ecubes. - Cubo:
origin(o canto mais baixo),sizeeuv(onde a textura dele começa na imagem). O layout é o usual de caixa: um cubo de largura w, altura h e profundidade d usa uma área de 2(w+d) por (d+h) pixels. - As animações vão por osso, como um nome ou uma lista de nomes:
| Animação | O que faz |
|---|---|
look |
Gira para onde a criatura olha; para cabeças. |
walk, walk_opposite |
Balança ao andar; a segunda em fase oposta, para o outro membro. |
idle |
Um leve balanço. |
spin |
Continua girando. |
"idle": { "length": 1.2, "interpolation": "smooth", "bones": {
"left_wing": { "rotation": { "0": [0, 0, -20], "0.6": [0, 0, 25], "1.2": [0, 0, -20] } } } }Um clipe iniciado pelo código toca por cima de walk, idle e attack em vez de substituí-los, e eles se somam: uma criatura pode rugir enquanto anda.
Se um modelo não puder ser desenhado, a criatura fica com a aparência do corpo e o log diz o motivo.
Tamanho
Uma criatura tem o tamanho do seu corpo. Quando o seu modelo é menor ou maior, defina size: [width, height] em blocos para que aquilo com que ela colide e onde se clica nela correspondam ao que os jogadores veem:
creature "drake" {
body: "minecraft:bee"
model: "entity/drake"
texture: "entity/drake"
size: [1.4, 1.1]
}Em Kotlin: size = 1.4 to 1.1.
Animações por quadros-chave
Para movimentos além das animações prontas, adicione uma seção clips ao lado de bones e 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] } } } }
} }- Cada clipe tem um
length(duração) em segundos e, por osso, até três canais:rotationem graus,positionem pixels (y para cima) escale(um número ou[x, y, z]). - As chaves são tempos em segundos. Os valores se misturam em linha reta entre as chaves; adicione
"interpolation": "smooth"a um clipe e ele passa pelas suas chaves em uma curva. Um canal também pode ser um único valor para o clipe todo.
| Clipe | Quando toca |
|---|---|
walk |
Repete enquanto ela anda, no ritmo dos pés. |
idle |
Repete enquanto ela fica parada. |
attack |
Toca quando ela golpeia. |
| Qualquer outro nome | Toca quando o código pede: c.play_animation("roar"). Jogadores próximos que têm o Crafting a veem. |
Filhotes de uma criatura com modelo próprio são desenhados com metade do tamanho.
Texturas
Sem um modelo, a textura tem o mesmo layout da do corpo escolhido (um zumbi, um lobo…), então você pode partir de um modelo desse corpo e pintar por cima. Ela vai dentro do mod, como as texturas de itens e blocos:
| Mod | Onde |
|---|---|
| CraftScript (pasta) | mods/ghostmod/textures/entity/ghost.png |
| Kotlin ou Java | src/main/resources/assets/ghostmod/textures/entity/ghost.png |