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

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

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

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

content/Armor.ktKotlin
item("frost_helmet") { armor(EquipmentSlot.HEAD, defense = 3, texture = "frost") }

Blocos

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

content/drops.craftCraftScript
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 seu count como nos minérios do jogo, ou uma chance melhor 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).

content/Drops.ktKotlin
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

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

content/wands.craftCraftScript
import { lift } from "/lib/teleport"

item "lift_wand" { stack: 1, rarity: "uncommon", on_use: lift }
lib/teleport.craftCraftScript
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.
content/reactions.craftCraftScript
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:

content/Reactions.ktKotlin
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á:

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

content/Portals.ktKotlin
block("sky_gate") { portal("gatemod:sky") }

Estados de bloco

states dá ao bloco valores que ele lembra e pode mostrar:

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

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

content/States.ktKotlin
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.

content/frozen.craftCraftScript
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, harmful ou neutral.
  • 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>.png do 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/Frozen.ktKotlin
content.effect("frozen") {
    color = 0x88CCFF
    kind = EffectKind.HARMFUL
    onTick = { e, level -> /* … */ }
}

Redstone

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

content/Battery.ktKotlin
block("battery") {
    texture = "minecraft:block/copper_block"
    redstone = true
    // in a handler: ctx.block.redstonePower
}

Inventários

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

content/Crate.ktKotlin
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:

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

content/Pedestal.ktKotlin
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

content/Blocks.ktKotlin
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.