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

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] } ]
}
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

commands/haunt.craftCraftScript
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.

content/ghost.craftCraftScript
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/Creatures.ktKotlin
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:

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!"
}

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.

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: 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 a can_start.
  • moves: true por 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. Use false para 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:

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 }]
}
  • Criar. breed_item mais 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 criatura rideable com 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:

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: dano causado a quem ele atinge.
  • gravity: false faz com que voe em linha reta.
  • on_hit: fun(e), chamado quando ele cai, com o mesmo e do evento hit: e.projectile, e.shooter e e.entity ou e.block.
  • texture: o projétil voa com a aparência do seu item, então por padrão usa textures/item/<id>.png; defina texture para 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/FrostBolt.ktKotlin
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.

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
    }
}
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:

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)

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, damage e entity_death, tem data, e você a manipula com o que está em O mundo e os jogadores.

Em 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)
        }
    }
}

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.

content/robot.craftCraftScript
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.

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" } }

As medidas são em pixels (16 é um bloco), com y apontando para cima a partir dos pés da criatura.

  • Osso: name, um parent opcional (ele se move junto), pivot (o ponto em torno do qual gira) e cubes.
  • Cubo: origin (o canto mais baixo), size e uv (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.
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] } } } }

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:

content/drake.craftCraftScript
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:

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] } } } }
  } }
  • Cada clipe tem um length (duração) em segundos e, por osso, até três canais: rotation em graus, position em pixels (y para cima) e scale (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