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
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
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.
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.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:
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à.
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 acan_start.moves:trueper impostazione predefinita. Un comportamento che si muove non gira insieme a un altro che si muove; vince quello più in alto nella lista. Usafalseper 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:
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_itempiù 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 creaturarideablecon 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:
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:falselo fa volare in linea retta.on_hit:fun(e), chiamata quando atterra, con lo stessoedell’eventohit:e.projectile,e.shooteree.entityoe.block.texture: il proiettile vola con l’aspetto del suo oggetto, quindi di default usatextures/item/<id>.png; impostatextureper 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.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.
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:
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,damageedentity_death, hadata, e la gestisci con ciò che trovi in Il mondo e i giocatori.
In 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)
}
}
}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.
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.
{ "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, unparentopzionale (si muove con lui),pivot(il punto attorno a cui ruota) ecubes. - Cubo:
origin(il suo angolo più basso),sizeeuv(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:
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:
{ "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:rotationin gradi,positionin pixel (y verso l’alto) escale(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. |
"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 |