API

Creature

Una creatura personalizzata usa il corpo di una creatura del gioco (il suo modello, le animazioni, la dimensione e il modo di muoversi) con la tua texture dipinta sopra, le tue statistiche, il tuo comportamento e il tuo bottino. La dichiari come il resto dei contenuti: un elenco di proprietà.

Dichiarare una creatura

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] } ]
}
Proprietà Valori Predefinito
body id di una creatura del gioco: minecraft:zombie, minecraft:wolf, minecraft:cow… obbligatorio
texture percorso della texture, dipinta sul modello del corpo: entity/ghost è il file textures/entity/ghost.png della mod l’aspetto del corpo
model il tuo modello 3D: entity/robot è il file models/entity/robot.json della mod (sotto) il modello del corpo
size [larghezza, altezza] in blocchi: con cosa collide e dove si clicca (sotto) quella del corpo
health punti salute quelli del corpo
speed velocità di camminata (uno zombie si muove a 0.23, un lupo a 0.3) quella del corpo
attack danno dell’attacco ravvicinato quello del corpo
follow_range a quanti blocchi di distanza rileva i suoi bersagli quello del corpo
behaviour elenco di comportamenti, dal più al meno importante (vedi sotto) il comportamento del corpo
targets chi attacca, in ordine di priorità (vedi sotto) nessuno
loot [{ item, count, chance }, …], come per i blocchi: ogni oggetto viene estratto separatamente niente
spawns biomi in cui compare da sola, con peso e dimensione del gruppo (sotto) non compare da sola
breed_item oggetto che fa riprodurre due esemplari (sotto) non si riproduce
tame_item oggetto che la addomestica (sotto) non si può addomesticare
rideable true permette ai giocatori di cavalcarla (sotto) false

Comportamenti

L’elenco è la priorità: quando due vogliono agire insieme, vince quello che viene prima. Scrivi ognuno come nome, come { name: number } per la sua impostazione principale, oppure come mappa con tutte le sue impostazioni.

Comportamento Cosa fa Impostazioni
"swim" Resta a galla nell’acqua.
"look_around" Si guarda intorno quando è inattiva.
"wander", { wander: 0.8 } Vaga qua e là. speed, predefinito 1
"look_at_players", { look_at_players: 10 } Guarda i giocatori vicini. range in blocchi, predefinito 8
"melee_attack", { melee_attack: 1.2 } Insegue e colpisce il suo bersaglio. speed, predefinito 1
"panic", { panic: 1.5 } Scappa quando subisce danni. speed, predefinito 1.25
{ avoid: "minecraft:wolf", distance: 8, speed: 1.2 } Sta lontana da quella creatura. distance in blocchi, speed
{ follow: "minecraft:wheat", speed: 1 } Segue chi tiene in mano quell’oggetto. speed
{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 } Spara un proiettile al suo bersaglio (sotto). projectile, interval, range, speed, power, damage
"breed", { breed: 1 } Si riproduce con un’altra della sua specie dopo essere stata nutrita. speed
"follow_parent", { follow_parent: 1.1 } Un cucciolo resta vicino al genitore. speed
{ follow_owner: 1.2, distance: 8 } Una creatura addomesticata segue il suo padrone. speed, distance in blocchi
{ fly_around: 1 } Vola in giro; per corpi volanti (pappagallo, ape, allay). speed
{ can_start: …, tick: … } Il tuo codice (sotto). can_start, tick, keep_going, moves

I numeri di velocità moltiplicano la velocità base della creatura: { wander: 0.8 } vaga un po’ più lentamente di come cammina.

Bersagli

targets dice chi attacca, dalla priorità più alta alla più bassa. "hurt_by" è chi le infligge danni; un id di entità è l’entità più vicina di quel tipo ("minecraft:player" per i giocatori, "minecraft:pig" per i maiali). Perché l’attacco avvenga, la creatura ha bisogno di un comportamento che lo esegua, come "melee_attack".

Generarla

commands/haunt.craftCraftScript
command haunt requires "ghostmod.haunt" describe "Evoca un fantasma dove ti trovi" {
    if player == null { return "Solo per giocatori" }
    world().spawn("ghostmod:ghost", player.location)
    return "&7Appare un fantasma…"
}

L’id è quello della tua mod: ghostmod:ghost. Funziona anche il comando del gioco /summon ghostmod:ghost.

Comparire da sole

Aggiungi spawns e la creatura compare da sola nel mondo, come le creature del gioco.

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

Ogni voce indica i biomes in cui compare (un id, o un #tag per un intero gruppo di biomi), un weight (peso: quanto spesso, rispetto alle altre creature di quel bioma; una mucca vale 8, uno zombie 95) e un intervallo per la dimensione del group (gruppo).

Segue le regole di comparsa del suo corpo: con un corpo da zombie compare al buio, con un corpo da mucca sull’erba, alla luce. Vale sia alla generazione del mondo sia dopo.

Uovo generatore. Ogni creatura riceve anche un uovo generatore, il suo id più _spawn_egg (ghost_spawn_egg), nella scheda creativa delle uova generatore. La sua texture è textures/item/ghost_spawn_egg.png del mod, se esiste; altrimenti ha l’aspetto dell’uovo del suo corpo.

In Kotlin:

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

Guidare una creatura dal codice

Le creature che dichiari, e qualsiasi altro mob, sono una Creature. Da un evento, un comando o un timer puoi dare loro degli ordini:

Membro Cosa fa
target Chi sta attaccando. Si legge e si imposta.
moveTo(location, speed), move_to Cammina fino a una posizione. La velocità moltiplica quella normale.
stop() Smette di camminare.
isMoving, is_moving Se sta andando da qualche parte.
lookAt(location), look_at Si gira a guardare una posizione.
canSee(entity), can_see Se ha una linea di vista libera verso quell’entità.
isBaby Se è un cucciolo.
ownerId L’id del suo padrone, una volta addomesticata.
tame(player) Rende quel giocatore il suo padrone.
isSitting Se è seduta.
playAnimation(name), play_animation Riproduce una delle animazioni del suo modello (vedi sotto).

Ogni entità ha una velocity, un Vector in blocchi per tick. Leggila o impostala per spingere l’entità: entity.velocity = vector(0, 0.6, 0) la lancia verso l’alto.

In CraftScript, un let con tipo restringe un’entità a una creatura. Viene verificato in esecuzione:

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

Comportamenti tuoi

Quando quelli pronti non bastano, scrivine uno con il tuo codice. Va nella lista behaviour come gli altri, quindi la sua posizione è la sua priorità.

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: viene chiesto ogni pochi tick; restituisci se deve iniziare.
  • tick: viene eseguito a ogni tick finché il comportamento è attivo.
  • keep_going: dice se deve continuare. Se omesso, è uguale a can_start.
  • moves: true per impostazione predefinita. Un comportamento che si muove non gira insieme a un altro che si muove; vince quello più in alto nella lista. Usa false per quelli che solo guardano o reagiscono.

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

Animali: allevare, addomesticare, cavalcare e volare

Poche proprietà e comportamenti trasformano una creatura in un animale. Questa si riproduce con le mele, si addomestica con un osso e si può cavalcare:

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 }]
}
  • Allevare. breed_item più il comportamento "breed": nutrite con quell’oggetto, due della stessa specie fanno un cucciolo di quella specie. Serve un corpo da animale (mucca, lupo, gallina…). I cuccioli usano "follow_parent" per restare vicino ai genitori.
  • Addomesticare. tame_item: ogni tentativo riesce una volta su tre. Il padrone viene ricordato, e una creatura addomesticata non prende mai di mira il suo padrone. Accovacciati e usa a mano vuota per farla sedere o alzare. { follow_owner: 1.2, distance: 8 } le fa seguire il padrone.
  • Cavalcare. rideable: true: usa a mano vuota per salire (una volta addomesticata, solo il padrone). Si guida con i tasti di movimento e il mouse; accovacciati per scendere.
  • Volare. { fly_around: 1 } per corpi volanti (pappagallo, ape, allay). Una creatura rideable con corpo volante sale quando chi la cavalca guarda in alto e scende in picchiata quando guarda in basso.

In Kotlin: breedItem = …, tameItem = …, rideable = true e i comportamenti Behaviour.Breed(), Behaviour.FollowParent(), Behaviour.FollowOwner(speed, distance) e Behaviour.FlyAround().

Proiettili tuoi

Oltre a quelli del gioco, una mod può dichiarare i propri proiettili. Ha un suo danno, una sua gravità e ciò che succede quando atterra:

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: il danno inflitto a ciò che colpisce.
  • gravity: false lo fa volare in linea retta.
  • on_hit: fun(e), chiamata quando atterra, con lo stesso e dell’evento hit: e.projectile, e.shooter e e.entity o e.block.
  • texture: il proiettile vola con l’aspetto del suo oggetto, quindi di default usa textures/item/<id>.png; imposta texture per usarne un’altra.

Usalo come qualsiasi altro proiettile: world.shoot("mymod:frost_bolt", from, velocity, shooter), oppure, in una creatura, { ranged_attack: "mymod:frost_bolt" }. In Kotlin:

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

Attacchi a distanza e proiettili

Il comportamento ranged_attack fa sparare una creatura. Si avvicina finché il bersaglio è a tiro e in vista, poi spara.

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
    }
}
Impostazione Significato
ranged_attack ranged_attack: il proiettile (minecraft:arrow, minecraft:snowball, minecraft:small_fireball, minecraft:wind_charge…).
interval interval: tick tra un colpo e l’altro.
range range: distanza in blocchi da cui spara.
speed speed: velocità di camminata mentre si avvicina.
power power: quanto veloce vola il proiettile.
damage damage: danno extra quando colpisce.

Per sparare dal codice, con creature o con l’abilità di un giocatore, usa world().shoot(projectile, from, velocity, shooter, damage).

In 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)

L’evento hit (ProjectileHitEvent) scatta quando un proiettile colpisce. Ha e.projectile, e.shooter e e.entity oppure e.block, a seconda di cosa ha colpito. Annullalo e il proiettile passa attraverso. Vedi Eventi.

Buono a sapersi

  • Ogni corpo ha i suoi limiti. Ad alcune creature del gioco manca una statistica: una mucca non ha danno d’attacco. Se la imposti, viene ignorata e Crafting avvisa nel log.
  • Corpi che non camminano. I corpi che non sanno trovare un percorso da soli ignorano i comportamenti di movimento (vagare, inseguire, panico, seguire, evitare); gli altri funzionano.
  • Senza behaviour, la creatura si comporta come il corpo che usa. Appena scrivi l’elenco, fa solo ciò che contiene.
  • Il modello cambia solo l’aspetto. Movimento e comportamento vengono sempre dal corpo, e anche la dimensione, a meno che tu non imposti size.
  • Una creatura personalizzata è un’entità vivente come le altre: riceve gli eventi spawn, damage ed entity_death, ha data, e la gestisci con ciò che trovi in Il mondo e i giocatori.

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

Comportamenti: Behaviour.Swim, LookAround, Wander(speed), LookAtPlayers(range), MeleeAttack(speed), Panic(speed), Avoid(entity, distance, speed), Follow(item, speed). Bersagli: TargetRule.HurtBy e TargetRule.Nearest(id). Aggiungi il bottino con drop(item, count, chance), come per i blocchi.

Il tuo modello 3D

Aggiungi model e la creatura viene disegnata con il tuo modello invece di quello del corpo. Il corpo le dà comunque dimensione, movimento e comportamento; il modello cambia solo il suo aspetto.

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

Il modello è il file models/entity/robot.json della mod e la sua texture è textures/entity/robot.png. In Kotlin: creature("robot") { body = "minecraft:pig"; model = "entity/robot"; texture = "entity/robot" }. Il formato è lo stesso in tutte le versioni del gioco.

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

Le misure sono in pixel (16 è un blocco), con y che sale dai piedi della creatura.

  • Osso: name, un parent opzionale (si muove con lui), pivot (il punto attorno a cui ruota) e cubes.
  • Cubo: origin (il suo angolo più basso), size e uv (dove inizia la sua texture nell’immagine). La disposizione è quella solita della scatola: un cubo di larghezza w, altezza h e profondità d usa un’area di 2(w+d) per (d+h) pixel.
  • Le animazioni vanno per osso, come un nome o un elenco di nomi:
Animazione Cosa fa
look Gira dove guarda la creatura; per le teste.
walk, walk_opposite Oscilla mentre cammina; la seconda in fase opposta, per l’altro arto.
idle Un leggero ondeggiamento.
spin Continua a girare.

Se un modello non può essere disegnato, la creatura ha l’aspetto del suo corpo e il log spiega perché.

Dimensione

Una creatura è grande quanto il suo corpo. Quando il tuo modello è più piccolo o più grande, imposta size: [larghezza, altezza] in blocchi, così che ciò con cui collide e il punto in cui si clicca corrispondano a ciò che vedono i giocatori:

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

In Kotlin: size = 1.4 to 1.1.

Animazioni a fotogrammi chiave

Per movimenti oltre le animazioni pronte, aggiungi una sezione clips accanto a 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] } } } }
  } }
  • Ogni clip ha una length (durata) in secondi e, per osso, fino a tre canali: rotation in gradi, position in pixel (y verso l’alto) e scale (un numero o [x, y, z]).
  • Le chiavi sono tempi in secondi. I valori si fondono in linea retta tra le chiavi; aggiungi "interpolation": "smooth" a una clip e passerà per le sue chiavi lungo una curva. Un canale può anche essere un solo valore per tutta la clip.
Clip Quando parte
walk Si ripete mentre cammina, al ritmo dei suoi piedi.
idle Si ripete mentre sta ferma.
attack Parte quando colpisce.
Qualsiasi altro nome Parte quando il codice lo chiede: c.play_animation("roar"). I giocatori vicini che hanno Crafting la vedono.
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] } } } }

Una clip avviata dal codice viene riprodotta sopra walk, idle e attack invece di sostituirle, e si sommano: una creatura può ruggire mentre cammina.

I cuccioli di una creatura con modello proprio vengono disegnati a metà dimensione.

Texture

Senza modello, la texture ha la stessa disposizione di quella del corpo scelto (uno zombie, un lupo…), quindi puoi partire da un modello per quel corpo e dipingerci sopra. Va dentro la mod, come le texture di oggetti e blocchi:

Mod Dove
CraftScript (cartella) mods/ghostmod/textures/entity/ghost.png
Kotlin o Java src/main/resources/assets/ghostmod/textures/entity/ghost.png