API
Blocos, itens e receitas
Você declara o conteúdo como uma lista de propriedades. O Crafting cria os objetos reais do jogo no momento certo e gera os modelos, tabelas de loot, tags, receitas e traduções de que eles precisam. Você não escreve nenhum arquivo de dados do jogo.
Itens
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" }| Propriedade | Valores | Padrão |
|---|---|---|
stack ou max_stack |
1–99 | 64 |
rarity |
common, uncommon, rare, epic (cor do nome) |
common |
glint |
brilho de encantamento | false |
durability |
número; força stack: 1 |
0 |
fireproof |
não queima na lava nem no fogo | false |
food |
número, ou { nutrition, saturation, always_edible } |
— |
tool |
"pickaxe", ou { type, tier, damage, speed }; type: pickaxe, axe, shovel, hoe, sword |
— |
tab |
aba do inventário criativo (abaixo) | ingredients |
texture |
caminho da textura | item/<id> |
on_use |
fun(player, stack); retorna true se tratar o uso |
— |
armor |
{ slot, defense, toughness, knockback_resistance, texture } |
— |
on_hit |
fun(attacker, target, stack) |
— |
cooldown |
segundos | 0 |
Armadura, armas e tempos de recarga
Um item com armor pode ser vestido. slot é head, chest, legs ou feet. defense, toughness e knockback_resistance (de 0 a 1) são os valores de armadura do jogo: um peitoral de ferro tem 6 de defesa, o diamante 2 de resistência.
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 é como ela fica vestida. frost significa textures/entity/equipment/humanoid/frost.png no mod e, para as pernas, textures/entity/equipment/humanoid_leggings/frost.png, com a mesma disposição das texturas de armadura do jogo. Sem ela, a armadura parece de ferro.
on_hit é executado quando o item é usado para golpear, seja por um jogador ou por um 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 (em segundos) bloqueia o item por esse tempo depois de cada uso que o seu on_use tratou, e a barra de atalhos o mostra. Pelo código: player.set_cooldown("minecraft:feather", 2) e player.has_cooldown(id). Em Kotlin: armor(EquipmentSlot.HEAD, defense = 3, texture = "frost") para armaduras e onHit = { ctx -> … } para armas (ctx.attacker, ctx.target, ctx.stack).
item("frost_helmet") { armor(EquipmentSlot.HEAD, defense = 3, texture = "frost") }Blocos
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] }| Propriedade | Valores | Padrão |
|---|---|---|
hardness |
número; -1 = inquebrável |
1.5 |
resistance |
resistência a explosões | = hardness |
light |
0–15 | 0 |
light_when |
um estado do tipo interruptor, como "lit": o bloco só brilha enquanto está ligado (veja Estados de bloco) |
sempre |
sound |
stone, wood, gravel, grass, metal, glass, wool, sand | stone |
like |
um bloco com o qual ele é feito igual, do jogo ("minecraft:end_stone") ou seu: a dureza, a resistência, o som e se precisa da ferramenta certa para dropar algo são os desse bloco |
— |
kind |
um dos tipos do jogo: escadas, porta, baú, plantação… (veja Tipos de bloco) | cube |
tool, tier |
ferramenta necessária para o bloco dropar algo, e o material mínimo dessa ferramenta: wood, stone, iron, diamond, netherite | —, wood |
drops, drop_count |
um único item: id; número ou [min, max] |
o próprio bloco, 1 |
loot |
vários itens: [{ item, count, chance, tool, fortune }, …]. Cada um é sorteado separadamente; count é um número ou [min, max] e chance vai de 0 a 1 (padrão 1). tool e fortune: veja Drops: ferramentas e fortuna abaixo |
— |
friction |
0.6 normal, 0.98 gelo | 0.6 |
transparent |
dá para ver através dele (vidro, folhas) | false |
has_item |
registra também o item do bloco; sem ele, o bloco não dropa nada a menos que drops ou loot digam o quê |
true |
tab |
aba do inventário criativo | building_blocks |
on_use |
fun(player, block); retorna true se tratar o uso. Um jogador que se agacha com algo na mão o coloca no lugar, como com os blocos do jogo |
— |
Abas: building_blocks, colored_blocks, natural_blocks, functional_blocks, redstone_blocks, tools_and_utilities, combat, food_and_drinks, ingredients, spawn_eggs. Em Kotlin, elas ficam em CreativeTabs.
Para fazer uma criatura dropar algo a mais quando morre, adicione-o a e.drops no evento entity_death (veja Eventos).
Blocos que não são cubos, blocos dos tipos do jogo, criaturas, minérios, sons e partículas são declarados do mesmo jeito e têm páginas próprias: Formas de blocos, Tipos de bloco, Criaturas, Geração de mundo, Sons e partículas.
Drops: ferramentas e fortuna
Um drop em loot pode exigir uma ferramenta, e a fortuna pode dar mais dele:
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": só dropa quando o bloco é quebrado com toque suave.tool: "shears": só com tesoura ou toque suave, como as folhas e trepadeiras do jogo dropam a si mesmas.- Quando alguns drops exigem uma ferramenta, os que não exigem acontecem só quando essa ferramenta não é usada: o minério acima dropa a si mesmo com toque suave e os seus rubis nos demais casos.
fortune: true: a fortuna dá mais dele, mais do seucountcomo nos minérios do jogo, ou umachancemelhor como nas mudas que as folhas soltam.
Em 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)
}Receitas
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 ao usar
on_use é a única lógica que fica junto dos dados. Se passar de umas duas linhas, escreva a função em lib/ e importe-a:
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
}Blocos que reagem
Um bloco pode executar código quando algo acontece com ele ou ao redor dele. Cada manipulador recebe o bloco e, quando se aplica, a entidade.
| Propriedade | É executado quando |
|---|---|
on_step: fun(block, entity) |
uma entidade pisa no bloco. |
on_inside: fun(block, entity) |
uma entidade está dentro do bloco. O bloco precisa deixar as entidades passarem: um portal, uma planta ou uma forma não sólida. |
on_random_tick: fun(block) |
de vez em quando, ao acaso, como o crescimento das plantações: cerca de uma vez a cada 68 segundos por bloco. |
on_tick: fun(block) |
o tempo pedido com block.schedule(ticks) passou (20 ticks = 1 segundo). |
on_neighbor_change: fun(block) |
um bloco vizinho mudou: foi colocado, quebrado ou energizado. |
on_placed: fun(block, entity) |
alguém colocou o bloco; entity é quem. |
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) }
}Em Kotlin os manipuladores são onStep, onInside, onRandomTick, onTick, onNeighborChange e onPlaced. Cada um recebe um BlockEventContext com block e, quando há, entity:
block("pad") { onStep = { ctx -> ctx.entity?.velocity = Vector(0.0, 1.1, 0.0) } }Portais
Um bloco com portal leva quem está dentro dele para outra dimensão. Indique a dimensão de destino, ou to e back para escolher aonde leva a partir de lá:
block "sky_gate" { portal: "gatemod:sky", light: 11 }
block "sky_gate_two_way" { portal: { to: "gatemod:sky", back: "minecraft:overworld" } }A entidade chega ao chão nas mesmas x e z e ali encontra um bloco de portal para voltar; se não houver nenhum por perto, um é colocado ao lado da chegada. As entidades esperam um momento antes de usar um portal de novo. Os blocos de portal deixam as entidades passarem. A própria dimensão se declara com dimension (veja @dim@). Em Kotlin:
block("sky_gate") { portal("gatemod:sky") }Estados de bloco
states dá ao bloco valores que ele lembra e pode mostrar:
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": norte, leste, sul ou oeste. Fica voltado para o jogador que o coloca, e o modelo gira junto."lit": um nome sozinho é um interruptor ligado/desligado, desligado por padrão.{ lit: true }o deixa ligado por padrão.{ stage: 3 }: um número de 0 até o máximo indicado (de 1 a 15)."facing_all": como"facing", mas também para cima e para baixo. Fica voltado para o jogador que o coloca, e o modelo é inclinado para cima e para baixo.{ shape: ["top", "middle", "bottom"] }: um entre alguns nomes, o primeiro por padrão. Os nomes são letras minúsculas, dígitos e_.
Leia e altere com block.state("lit") e block.set_state("lit", true). Também funciona com os blocos do jogo, por exemplo o facing e o lit de uma fornalha.
Um estado diferente do padrão pode ter outra aparência. Adicione uma textura em textures/block/<id>_<nome>.png (um interruptor ligado) ou <id>_<nome><n>.png (um número) ou <id>_<valor>.png (um nome), ou um modelo em models/block/<id>_<nome>.json. A combinação completa (<id>_lit_stage2) é tentada primeiro, depois cada estado sozinho. No exemplo, lamp.json e lamp_lit.json são os dois modelos do mod, por exemplo com o pai minecraft:block/orientable e texturas de frente, lado e topo.
Luz por estado. light_when: "lit" faz o light do bloco brilhar apenas enquanto esse interruptor está ligado, como em uma lâmpada:
block "lamp" {
light: 15
light_when: "lit"
states: ["lit"]
on_use: fun(p, b) { b.set_state("lit", !b.state("lit")); return true }
}Em Kotlin: facing(), facingAll(), toggle("lit"), number("stage", 3), choice("shape", "top", "middle", "bottom"), e block.state(…) e block.setState(…) no código:
block("lamp") {
model = "block/lamp"
facing()
toggle("lit")
number("stage", 3)
}Efeitos
Um mod pode adicionar seus próprios efeitos de estado. Eles aparecem na tela do jogador como os do jogo e são aplicados e consultados da mesma forma.
effect "frozen" {
color: "#88CCFF"
kind: "harmful"
on_tick: fun(e, level) { e.damage(level) }
}color: a cor das suas partículas e do fundo do ícone.kind:beneficial,harmfulouneutral.on_tick:fun(e, level), roda a cada segundo enquanto uma entidade tem o efeito, com o nível dele (1 é I).- O ícone é o
textures/mob_effect/<id>.pngdo mod.
Aplique-o com e.add_effect("mymod:frozen", 3, 1) (id, segundos, nível) e consulte-o com e.has_effect("mymod:frozen"), como nos efeitos do jogo (veja O mundo e os jogadores). Em 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 faz o bloco emitir um sinal tão forte quanto o seu estado power, um número de 0 a 15 adicionado automaticamente. b.set_state("power", 15) o liga, e os fios, lâmpadas e portas ao redor acompanham. block.redstone_power é a potência que o bloco recebe do entorno, e on_neighbor_change é executado quando ela muda (a lâmpada acima usa isso).
Em Kotlin: redstone = true e block.redstonePower.
block("battery") {
texture = "minecraft:block/copper_block"
redstone = true
// in a handler: ctx.block.redstonePower
}Inventários
block "crate" { texture: "minecraft:block/barrel_side", inventory: 27 }inventory: 27 dá ao bloco essa quantidade de espaços (de 9 a 54, em fileiras de 9). Ele guarda os itens entre reinícios, usá-lo abre uma tela de baú (a menos que o seu on_use tenha ficado com o clique) e quebrá-lo solta o que ele guarda. De 1 a 8 espaços não há tela: o próprio mod coloca e tira os itens.
No código, block.inventory (também funciona para os baús e barris do jogo) oferece set(slot, item(…)), get(slot), count(id) e add(…). Em Kotlin: inventory = 27.
block("crate") {
texture = "minecraft:block/barrel_side"
inventory = 27
}Itens exibidos sobre um bloco. shows_item: 14 faz o item do primeiro espaço do bloco flutuar acima dele, girando, a tantos pixels acima da sua base. Todos os jogadores o veem, e ele some quando o espaço se esvazia ou o bloco é quebrado. Um pedestal pega o item da mão do jogador e o devolve:
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) coloca um item na mão principal do jogador, ou a esvazia com null. Em 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
}
}Texturas
As texturas vêm dentro do mod; ninguém precisa instalar um pacote de recursos. O nome do arquivo é o id:
| Mod | Onde |
|---|---|
| CraftScript (pasta) | mods/rubies/textures/item/ruby.png, mods/rubies/textures/block/ruby_ore.png |
| Kotlin ou Java | src/main/resources/assets/rubies/textures/item/ruby.png |
Se um mod traz seus próprios modelos, receitas ou tabelas de loot nessas mesmas pastas, o Crafting os usa.
Em 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 }
}
}Ids. Sem namespace, um id pertence ao seu mod ("ruby" é rubies:ruby). Para conteúdo do jogo, escreva o namespace: "minecraft:diamond". Você não pode registrar conteúdo no namespace minecraft.