API
Blocchi, oggetti e ricette
Dichiari i contenuti come un elenco di proprietà. Crafting crea i veri oggetti del gioco al momento giusto e genera i modelli, le tabelle del bottino, i tag, le ricette e le traduzioni di cui hanno bisogno. Non scrivi nessun file di dati del gioco.
Oggetti
item "ruby" { rarity: "rare" }
item "ruby_apple" {
food: { nutrition: 8, saturation: 1.2, always_edible: true }
glint: true
}
item "ruby_pickaxe" { tool: { type: "pickaxe", tier: "diamond", speed: 9 }, tab: "tools_and_utilities" }| Proprietà | Valori | Predefinito |
|---|---|---|
stack o max_stack |
1–99 | 64 |
rarity |
common, uncommon, rare, epic (colore del nome) |
common |
glint |
luccichio dell’incantesimo | false |
durability |
numero; impone stack: 1 |
0 |
fireproof |
non brucia nella lava o nel fuoco | false |
food |
numero, oppure { nutrition, saturation, always_edible } |
— |
tool |
"pickaxe", oppure { type, tier, damage, speed }; type: pickaxe (piccone), axe (ascia), shovel (pala), hoe (zappa), sword (spada) |
— |
tab |
scheda dell’inventario della modalità Creativa (vedi sotto) | ingredients |
texture |
percorso della texture | item/<id> |
on_use |
fun(player, stack); restituisce true se gestisce l’uso |
— |
armor |
{ slot, defense, toughness, knockback_resistance, texture } |
— |
on_hit |
fun(attacker, target, stack) |
— |
cooldown |
secondi | 0 |
Armature, armi e tempi di ricarica
Un oggetto con armor si può indossare. slot è head, chest, legs o feet. defense, toughness e knockback_resistance (da 0 a 1) sono i valori di armatura del gioco: un pettorale di ferro ha 6 di difesa, il diamante 2 di tenacia.
item "frost_helmet" { texture: "minecraft:item/iron_helmet", armor: { slot: "head", defense: 3, texture: "frost" } }
item "frost_chestplate" { armor: { slot: "chest", defense: 8, toughness: 2 }, durability: 400 }texture è l'aspetto da indossata. frost significa textures/entity/equipment/humanoid/frost.png nella mod e, per le gambe, textures/entity/equipment/humanoid_leggings/frost.png, con la stessa struttura delle texture di armatura del gioco. Senza, l'armatura sembra di ferro.
on_hit viene eseguito quando l'oggetto è usato per colpire, da un giocatore o da un mob.
item "frost_blade" {
texture: "minecraft:item/diamond_sword"
tool: "sword"
cooldown: 3
on_hit: fun(attacker, target, stack) {
target.add_effect("minecraft:slowness", 4, 4)
target.world.spawn_particle("minecraft:snowflake", target.location.add(0, 1, 0), 20, 0.4, 0.02)
}
}cooldown (in secondi) blocca l'oggetto per quel tempo dopo ogni uso che il suo on_use ha gestito, e la barra rapida lo mostra. Da codice: player.set_cooldown("minecraft:feather", 2) e player.has_cooldown(id). In Kotlin: armor(EquipmentSlot.HEAD, defense = 3, texture = "frost") per le armature e onHit = { ctx -> … } per le armi (ctx.attacker, ctx.target, ctx.stack).
item("frost_helmet") { armor(EquipmentSlot.HEAD, defense = 3, texture = "frost") }Blocchi
block "ruby_ore" {
hardness: 3
tool: "pickaxe"
tier: "iron"
loot: [
{ item: "rubies:ruby", count: [1, 2] },
{ item: "minecraft:diamond", chance: 0.1 }
]
}
block "ruby_block" { hardness: 5, light: 7, tool: "pickaxe", sound: "metal" }
block "ruby_lamp" { hardness: 0.3, light: 15, sound: "glass", transparent: true, tab: "functional_blocks" }
block "ruby_bricks" { hardness: 2, tool: "pickaxe", drops: "ruby", drop_count: [2, 4] }| Proprietà | Valori | Predefinito |
|---|---|---|
hardness |
numero; -1 = indistruttibile |
1.5 |
resistance |
resistenza alle esplosioni | = hardness |
light |
0–15 | 0 |
light_when |
uno stato interruttore, come "lit": il blocco illumina solo quando è acceso (vedi Stati del blocco) |
sempre |
sound |
stone, wood, gravel, grass, metal, glass, wool, sand | stone |
like |
un blocco con cui viene fatto uguale, del gioco ("minecraft:end_stone") o tuo: la sua durezza, resistenza, suono e se serve lo strumento giusto per rilasciare qualcosa sono quelli di quel blocco |
— |
kind |
uno dei tipi del gioco: scale, porta, baule, coltivazione… (vedi Tipi di blocco) | cube |
tool, tier |
strumento necessario perché il blocco rilasci qualcosa, e il materiale minimo di quello strumento: wood (legno), stone (pietra), iron (ferro), diamond (diamante), netherite (netherite) | —, wood |
drops, drop_count |
un solo oggetto: id; numero o [min, max] |
il blocco stesso, 1 |
loot |
più oggetti: [{ item, count, chance, tool, fortune }, …]. Ognuno viene estratto separatamente; count è un numero o [min, max] e chance va da 0 a 1 (predefinito 1). tool e fortune: vedi Drop: strumenti e fortuna più sotto |
— |
friction |
0.6 normale, 0.98 ghiaccio | 0.6 |
transparent |
ci si vede attraverso (vetro, foglie) | false |
has_item |
registra anche l’oggetto del blocco; senza, il blocco non rilascia nulla a meno che drops o loot dicano cosa |
true |
tab |
scheda dell’inventario della modalità Creativa | building_blocks |
on_use |
fun(player, block); restituisce true se gestisce l’uso. Un giocatore che si accovaccia con qualcosa in mano lo piazza al suo posto, come con i blocchi del gioco |
— |
Schede: building_blocks, colored_blocks, natural_blocks, functional_blocks, redstone_blocks, tools_and_utilities, combat, food_and_drinks, ingredients, spawn_eggs. In Kotlin si trovano in CreativeTabs.
Per far rilasciare qualcosa in più a una creatura quando muore, aggiungilo a e.drops nell’evento entity_death (vedi Eventi).
I blocchi che non sono cubi, i blocchi dei tipi del gioco, le creature, i minerali, i suoni e le particelle si dichiarano allo stesso modo e hanno le loro pagine: Forme dei blocchi, Tipi di blocco, Creature, Generazione del mondo, Suoni e particelle.
Drop: strumenti e fortuna
Un drop in loot può richiedere uno strumento, e la fortuna può darne di più:
block "ruby_ore" {
kind: "ore"
tool: "pickaxe"
tier: "iron"
xp: [1, 4]
loot: [
{ item: "ruby", count: [1, 2], fortune: true },
{ item: "ruby_ore", tool: "silk_touch" }
]
}
block "frost_leaves" {
kind: "leaves"
loot: [
{ item: "frost_leaves", tool: "shears" },
{ item: "frost_sapling", chance: 0.05, fortune: true }
]
}tool: "silk_touch": viene rilasciato solo quando il blocco è rotto con il tocco di velluto.tool: "shears": solo con le cesoie o il tocco di velluto, come le foglie e i rampicanti del gioco rilasciano sé stessi.- Quando alcuni drop richiedono uno strumento, quelli che non lo richiedono avvengono solo quando quello strumento non viene usato: il minerale qui sopra rilascia sé stesso con il tocco di velluto e i suoi rubini altrimenti.
fortune: true: la fortuna ne dà di più, più del suocountcome con i minerali del gioco, o unachancemigliore come con le piantine rilasciate dalle foglie.
In Kotlin: drop("ruby", 1..2, tool = null, fortune = true) e drop("ruby_ore", tool = DropTool.SILK_TOUCH).
block("ruby_ore") {
kind = BlockKind.ORE
xp = 1..4
drop("ruby", 1..2, tool = null, fortune = true)
drop("ruby_ore", tool = DropTool.SILK_TOUCH)
}Ricette
recipe shaped "ruby_block" {
pattern: ["RRR", "RRR", "RRR"]
keys: { R: "ruby" }
result: "ruby_block"
}
recipe shapeless "rubies_from_block" { ingredients: ["ruby_block"], result: "ruby", count: 9 }
recipe smelting "ruby_from_ore" { input: "ruby_ore", result: "ruby", xp: 1.0 }Comportamento all’uso
on_use è l’unica logica che vive accanto ai dati. Se supera un paio di righe, scrivi la funzione in lib/ e importala:
import { lift } from "/lib/teleport"
item "lift_wand" { stack: 1, rarity: "uncommon", on_use: lift }fun lift(player, stack) {
player.teleport(player.location.add(0, 10, 0))
return true
}Blocchi che reagiscono
Un blocco può eseguire codice quando succede qualcosa a lui o intorno a lui. Ogni gestore riceve il blocco e, dove serve, l'entità.
| Proprietà | Viene eseguito quando |
|---|---|
on_step: fun(block, entity) |
un'entità cammina sul blocco. |
on_inside: fun(block, entity) |
un'entità si trova dentro il blocco. Il blocco deve lasciar passare le entità: un portale, una pianta o una forma non solida. |
on_random_tick: fun(block) |
ogni tanto, a caso, come la crescita delle colture: circa ogni 68 secondi per blocco. |
on_tick: fun(block) |
è passato il tempo richiesto con block.schedule(ticks) (20 tick = 1 secondo). |
on_neighbor_change: fun(block) |
è cambiato un blocco adiacente: è stato piazzato, rotto o alimentato. |
on_placed: fun(block, entity) |
qualcuno ha piazzato il blocco; entity è chi. |
block "jump_pad" { on_step: fun(b, e) { e.velocity = vector(0, 1.1, 0) } }
block "blinker" {
light: 7
on_tick: fun(b) {
b.world.spawn_particle("minecraft:end_rod", b.location.add(0.5, 1.2, 0.5), 4, 0.1, 0.01)
b.schedule(20)
}
on_neighbor_change: fun(b) { b.schedule(1) }
}In Kotlin i gestori sono onStep, onInside, onRandomTick, onTick, onNeighborChange e onPlaced. Ognuno riceve un BlockEventContext con block e, se c'è, entity:
block("pad") { onStep = { ctx -> ctx.entity?.velocity = Vector(0.0, 1.1, 0.0) } }Portali
Un blocco con portal porta chi si trova al suo interno in un'altra dimensione. Indica la dimensione di destinazione, oppure to e back per scegliere dove porta da lì:
block "sky_gate" { portal: "gatemod:sky", light: 11 }
block "sky_gate_two_way" { portal: { to: "gatemod:sky", back: "minecraft:overworld" } }L'entità arriva a terra nelle stesse x e z e lì trova un blocco portale per tornare; se non ce n'è uno vicino, ne viene piazzato uno accanto all'arrivo. Le entità aspettano un momento prima di usare di nuovo un portale. I blocchi portale lasciano passare le entità. La dimensione si dichiara con dimension (vedi @dim@). In Kotlin:
block("sky_gate") { portal("gatemod:sky") }Stati del blocco
states dà a un blocco valori che ricorda e può mostrare:
block "lamp" {
model: "block/lamp"
states: ["facing", "lit"]
on_use: fun(p, b) { b.set_state("lit", !b.state("lit")); return true }
on_neighbor_change: fun(b) { b.set_state("lit", b.redstone_power > 0) }
}
block "crop" { states: [{ stage: 3 }, { wet: true }] }"facing": nord, est, sud od ovest. Si orienta verso il giocatore che lo piazza, e il modello ruota con lui."lit": un nome da solo è un interruttore acceso/spento, spento di default.{ lit: true }lo rende acceso di default.{ stage: 3 }: un numero da 0 al massimo indicato (da 1 a 15)."facing_all": come"facing", ma anche verso l’alto e verso il basso. Si orienta verso il giocatore che lo piazza, e il modello viene inclinato per l’alto e il basso.{ shape: ["top", "middle", "bottom"] }: uno tra pochi nomi, il primo di default. I nomi sono lettere minuscole, cifre e_.
Si leggono e si cambiano con block.state("lit") e block.set_state("lit", true). Funzionano anche con i blocchi del gioco, per esempio il facing e il lit di una fornace.
Uno stato diverso dal valore predefinito può avere un aspetto diverso. Aggiungi una texture in textures/block/<id>_<nome>.png (un interruttore acceso) o <id>_<nome><n>.png (un numero) o <id>_<valore>.png (un nome), oppure un modello in models/block/<id>_<nome>.json. Si prova prima la combinazione completa (<id>_lit_stage2), poi ogni stato da solo. Nell'esempio, lamp.json e lamp_lit.json sono i due modelli del mod, ad esempio con il parent minecraft:block/orientable e texture per fronte, lato e sopra.
Luce in base allo stato. light_when: "lit" fa sì che la light del blocco illumini solo mentre quell’interruttore è acceso, come in una lampada:
block "lamp" {
light: 15
light_when: "lit"
states: ["lit"]
on_use: fun(p, b) { b.set_state("lit", !b.state("lit")); return true }
}In Kotlin: facing(), facingAll(), toggle("lit"), number("stage", 3), choice("shape", "top", "middle", "bottom"), e block.state(…) e block.setState(…) nel codice:
block("lamp") {
model = "block/lamp"
facing()
toggle("lit")
number("stage", 3)
}Effetti
Una mod può aggiungere effetti di stato propri. Appaiono sullo schermo del giocatore come quelli del gioco e si danno e si leggono allo stesso modo.
effect "frozen" {
color: "#88CCFF"
kind: "harmful"
on_tick: fun(e, level) { e.damage(level) }
}color: il colore delle sue particelle e dello sfondo della sua icona.kind:beneficial,harmfuloneutral.on_tick:fun(e, level), viene eseguita ogni secondo finché un’entità ha l’effetto, con il suo livello (1 è I).- L’icona è il file
textures/mob_effect/<id>.pngdella mod.
Si dà con e.add_effect("mymod:frozen", 3, 1) (id, secondi, livello) e si controlla con e.has_effect("mymod:frozen"), come gli effetti del gioco (vedi Il mondo e i giocatori). In Kotlin:
content.effect("frozen") {
color = 0x88CCFF
kind = EffectKind.HARMFUL
onTick = { e, level -> /* … */ }
}Redstone
block "battery" {
texture: "minecraft:block/copper_block"
redstone: true
on_use: fun(p, b) { if b.state("power") > 0 { b.set_state("power", 0) } else { b.set_state("power", 15) }; return true }
}redstone: true fa emettere al blocco un segnale forte quanto il suo stato power, un numero da 0 a 15 aggiunto automaticamente. b.set_state("power", 15) lo accende, e fili, lampade e porte intorno lo seguono. block.redstone_power è la potenza che il blocco riceve dall'intorno, e on_neighbor_change viene eseguito quando cambia (la lampada qui sopra lo usa).
In Kotlin: redstone = true e block.redstonePower.
block("battery") {
texture = "minecraft:block/copper_block"
redstone = true
// in a handler: ctx.block.redstonePower
}Inventari
block "crate" { texture: "minecraft:block/barrel_side", inventory: 27 }inventory: 27 dà al blocco quel numero di slot (da 9 a 54, in file da 9). Conserva gli oggetti ai riavvii, usarlo apre una schermata da baule (a meno che il suo on_use abbia preso il clic) e rompendolo lascia cadere ciò che contiene. Da 1 a 8 slot non c’è nessuna schermata: è la mod stessa a mettere e togliere gli oggetti.
Dal codice, block.inventory (funziona anche con i bauli e i barili del gioco) offre set(slot, item(…)), get(slot), count(id) e add(…). In Kotlin: inventory = 27.
block("crate") {
texture = "minecraft:block/barrel_side"
inventory = 27
}Oggetti mostrati su un blocco. shows_item: 14 fa fluttuare l’oggetto del primo slot del blocco sopra di esso, ruotando, a tanti pixel sopra la sua base. Lo vedono tutti i giocatori, e sparisce quando lo slot si svuota o il blocco viene rotto. Un piedistallo prende l’oggetto dalla mano del giocatore e glielo restituisce:
block "pedestal" {
shape: [[2, 0, 2, 14, 12, 14]]
inventory: 1
shows_item: 14
on_use: fun(p, b) {
let inv = b.inventory
if inv.get(0) == null and p.held_item != null {
inv.set(0, p.held_item)
p.set_held_item(null)
} else if inv.get(0) != null {
p.give(inv.get(0))
inv.set(0, null)
}
return true
}
}player.set_held_item(stack) mette un oggetto nella mano principale del giocatore, o la svuota con null. In Kotlin: showsItem = 14 e player.setHeldItem(stack).
block("pedestal") {
box(2, 0, 2, 14, 12, 14)
inventory = 1
showsItem = 14
onUse { ctx ->
val inv = ctx.block.inventory!!
val held = ctx.player.heldItem
val shown = inv[0]
if (shown == null && held != null) { inv[0] = held; ctx.player.setHeldItem(null) }
else if (shown != null) { ctx.player.give(shown); inv[0] = null }
true
}
}Texture
Le texture sono incluse nella mod; nessuno deve installare un pacchetto di risorse. Il nome del file è l’id:
| Mod | Dove |
|---|---|
| CraftScript (cartella) | mods/rubies/textures/item/ruby.png, mods/rubies/textures/block/ruby_ore.png |
| Kotlin o Java | src/main/resources/assets/rubies/textures/item/ruby.png |
Se una mod include i propri modelli, ricette o tabelle del bottino in quelle stesse cartelle, Crafting li usa.
In Kotlin
package com.example.rubies.content
object Blocks {
fun register(content: ContentBuilder) {
content.block("ruby_ore") {
hardness = 3f
requiresTool = ToolType.PICKAXE
minTier = ToolTier.IRON
drop("ruby", 1..2)
drop("minecraft:diamond", chance = 0.1)
}
content.block("ruby_block") { hardness = 5f; luminance = 7; sound = SoundGroup.METAL }
}
}Id. Senza namespace, un id appartiene alla tua mod ("ruby" è rubies:ruby). Per i contenuti del gioco, scrivi il namespace: "minecraft:diamond". Non puoi registrare contenuti nel namespace minecraft.