API

Blocs, objets et recettes

Tu déclares le contenu sous forme de liste de propriétés. Crafting crée les vrais objets du jeu au bon moment et génère les modèles, les tables de butin, les tags, les recettes et les traductions nécessaires. Tu n’écris aucun fichier de données du jeu.

Objets

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" }
Propriété Valeurs Par défaut
stack ou max_stack 1–99 64
rarity common, uncommon, rare, epic (couleur du nom) common
glint reflet d’enchantement false
durability nombre ; impose stack: 1 0
fireproof ne brûle pas dans la lave ni dans le feu false
food nombre, ou { nutrition, saturation, always_edible } —
tool "pickaxe", ou { type, tier, damage, speed } ; type : pickaxe (pioche), axe (hache), shovel (pelle), hoe (houe), sword (épée) —
tab onglet de l’inventaire du mode Créatif (voir plus bas) ingredients
texture chemin de la texture item/<id>
on_use fun(player, stack) ; renvoie true si elle gère l’utilisation —
armor { slot, defense, toughness, knockback_resistance, texture } —
on_hit fun(attacker, target, stack) —
cooldown secondes 0

Armures, armes et temps de recharge

Un objet avec armor peut être porté. slot vaut head, chest, legs ou feet. defense, toughness et knockback_resistance (de 0 à 1) sont les valeurs d'armure du jeu : un plastron en fer a 6 de défense, le diamant 2 de robustesse.

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 est son apparence une fois portée. frost désigne textures/entity/equipment/humanoid/frost.png dans le mod et, pour les jambes, textures/entity/equipment/humanoid_leggings/frost.png, avec la même disposition que les textures d'armure du jeu. Sans elle, l'armure ressemble à du fer.

on_hit s'exécute quand l'objet sert à frapper, que ce soit un joueur ou une créature.

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 (en secondes) bloque l'objet pendant ce temps après chaque utilisation que son on_use a prise en charge, et la barre d'accès rapide l'affiche. Depuis le code : player.set_cooldown("minecraft:feather", 2) et player.has_cooldown(id). En Kotlin : armor(EquipmentSlot.HEAD, defense = 3, texture = "frost") pour les armures et onHit = { ctx -> … } pour les armes (ctx.attacker, ctx.target, ctx.stack).

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

Blocs

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] }
Propriété Valeurs Par défaut
hardness nombre ; -1 = incassable 1.5
resistance résistance aux explosions = hardness
light 0–15 0
light_when un état interrupteur, comme "lit" : le bloc n’éclaire que lorsqu’il est allumé (voir États de bloc) toujours
sound stone, wood, gravel, grass, metal, glass, wool, sand stone
like un bloc dont il est fait à l'image, celui du jeu ("minecraft:end_stone") ou le vôtre : sa dureté, sa résistance, son son et le fait qu'il faille le bon outil pour qu'il lâche quelque chose sont ceux de ce bloc —
kind une des sortes de blocs du jeu : escaliers, porte, coffre, culture… (voir Sortes de blocs) cube
tool, tier outil nécessaire pour que le bloc lâche quelque chose, et le matériau minimum de cet outil : wood, stone, iron, diamond, netherite —, wood
drops, drop_count un seul objet : id ; nombre ou [min, max] le bloc lui-même, 1
loot plusieurs objets : [{ item, count, chance, tool, fortune }, …]. Chacun est tiré séparément ; count est un nombre ou [min, max] et chance va de 0 à 1 (1 par défaut). tool et fortune : voir Butin ci-dessous —
friction 0.6 normal, 0.98 glace 0.6
transparent on voit à travers (verre, feuilles) false
has_item enregistre aussi l’objet du bloc ; sans lui, le bloc ne lâche rien, sauf si drops ou loot disent quoi true
tab onglet de l’inventaire du mode Créatif building_blocks
on_use fun(player, block) ; renvoie true si elle gère l’utilisation. Un joueur qui s'accroupit avec quelque chose en main le pose à la place, comme avec les blocs du jeu —

Onglets : building_blocks, colored_blocks, natural_blocks, functional_blocks, redstone_blocks, tools_and_utilities, combat, food_and_drinks, ingredients, spawn_eggs. En Kotlin, ils sont dans CreativeTabs.

Pour qu’une créature lâche quelque chose en plus à sa mort, ajoute-le à e.drops dans l’événement entity_death (voir Événements).

Les blocs qui ne sont pas des cubes, les blocs des sortes du jeu, les créatures, les minerais, les sons et les particules se déclarent de la même façon et ont leurs propres pages : Formes de blocs, Sortes de blocs, Créatures, Génération du monde, Sons et particules.

Butin : outils et fortune

Un objet de loot peut exiger un outil, et la fortune peut en donner davantage :

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" : il n'est lâché que si le bloc est cassé avec Toucher de soie. tool: "shears" : seulement avec des cisailles ou Toucher de soie, comme les feuilles et les lianes du jeu se lâchent elles-mêmes.
  • Quand certains butins exigent un outil, ceux qui n'en exigent pas n'ont lieu que si cet outil n'est pas utilisé : le minerai ci-dessus se lâche lui-même avec Toucher de soie et lâche ses rubis sinon.
  • fortune: true : la fortune en donne davantage, plus de son count comme avec les minerais du jeu, ou une meilleure chance comme avec les pousses des feuilles.

En Kotlin : drop("ruby", 1..2, tool = null, fortune = true) et 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)
}

Recettes

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 }

Comportement à l’utilisation

on_use est la seule logique qui vit à côté des données. Si elle dépasse deux ou trois lignes, écris la fonction dans lib/ et importe-la :

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
}

Des blocs qui réagissent

Un bloc peut exécuter du code quand il se passe quelque chose sur lui ou autour de lui. Chaque gestionnaire reçoit le bloc et, le cas échéant, l'entité.

Propriété S'exécute quand
on_step: fun(block, entity) une entité marche sur le bloc.
on_inside: fun(block, entity) une entité se trouve dans le bloc. Le bloc doit laisser passer les entités : un portail, une plante ou une forme non solide.
on_random_tick: fun(block) de temps en temps, au hasard, comme la pousse des cultures : environ toutes les 68 secondes par bloc.
on_tick: fun(block) le délai demandé avec block.schedule(ticks) est écoulé (20 ticks = 1 seconde).
on_neighbor_change: fun(block) un bloc voisin a changé : il a été posé, cassé ou alimenté.
on_placed: fun(block, entity) quelqu'un a posé le bloc ; entity est cette personne.
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) }
}

En Kotlin, les gestionnaires sont onStep, onInside, onRandomTick, onTick, onNeighborChange et onPlaced. Chacun reçoit un BlockEventContext avec block et, s'il y en a une, entity :

content/Reactions.ktKotlin
block("pad") { onStep = { ctx -> ctx.entity?.velocity = Vector(0.0, 1.1, 0.0) } }

Portails

Un bloc avec portal emmène celui qui s'y trouve vers une autre dimension. Indiquez la dimension de destination, ou to et back pour choisir où il mène depuis là :

content/portals.craftCraftScript
block "sky_gate" { portal: "gatemod:sky", light: 11 }

block "sky_gate_two_way" { portal: { to: "gatemod:sky", back: "minecraft:overworld" } }

L'entité arrive au sol aux mêmes x et z et y trouve un bloc de portail pour revenir ; s'il n'y en a aucun à proximité, on en place un à côté de l'arrivée. Les entités attendent un moment avant de réutiliser un portail. Les blocs de portail laissent passer les entités. La dimension elle-même se déclare avec dimension (voir @dim@). En Kotlin :

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

États de bloc

states donne à un bloc des valeurs qu'il retient et peut afficher :

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" : nord, est, sud ou ouest. Il est orienté vers le joueur qui le pose, et le modèle tourne avec lui.
  • "lit" : un nom seul est un interrupteur marche/arrêt, éteint par défaut. { lit: true } le rend allumé par défaut.
  • { stage: 3 } : un nombre de 0 au maximum indiqué (1 à 15).
  • "facing_all" : comme "facing", mais aussi vers le haut et vers le bas. Il est orienté vers le joueur qui pose le bloc, et le modèle est basculé pour le haut et le bas.
  • { shape: ["top", "middle", "bottom"] } : un nom parmi quelques-uns, le premier par défaut. Les noms sont faits de lettres minuscules, de chiffres et de _.

On les lit et on les change avec block.state("lit") et block.set_state("lit", true). Cela marche aussi pour les blocs du jeu, par exemple le facing et le lit d'un four.

Un état différent de sa valeur par défaut peut avoir un autre aspect. Ajoutez une texture dans textures/block/<id>_<nom>.png (un interrupteur allumé) ou <id>_<nom><n>.png (un nombre) ou <id>_<valeur>.png (un nom), ou un modèle dans models/block/<id>_<nom>.json. La combinaison complète (<id>_lit_stage2) est essayée en premier, puis chaque état seul. Dans l'exemple, lamp.json et lamp_lit.json sont les deux modèles du mod, par exemple avec le parent minecraft:block/orientable et des textures de face, de côté et de dessus.

Lumière selon l’état. light_when: "lit" fait que la light du bloc n’éclaire que lorsque cet interrupteur est allumé, comme une lampe :

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

En Kotlin : facing(), facingAll(), toggle("lit"), number("stage", 3), choice("shape", "top", "middle", "bottom"), et block.state(…) et block.setState(…) dans le code :

content/States.ktKotlin
block("lamp") {
    model = "block/lamp"
    facing()
    toggle("lit")
    number("stage", 3)
}

Effets

Un mod peut ajouter ses propres effets de statut. Ils apparaissent à l’écran du joueur comme ceux du jeu et se donnent et se lisent de la même façon.

content/frozen.craftCraftScript
effect "frozen" {
    color: "#88CCFF"
    kind: "harmful"
    on_tick: fun(e, level) { e.damage(level) }
}
  • color : la couleur de ses particules et du fond de son icône.
  • kind : beneficial, harmful ou neutral.
  • on_tick : fun(e, level), s’exécute chaque seconde tant qu’une entité a l’effet, avec son niveau (1 correspond à I).
  • L’icône est le fichier textures/mob_effect/<id>.png du mod.

On le donne avec e.add_effect("mymod:frozen", 3, 1) (id, secondes, niveau) et on le vérifie avec e.has_effect("mymod:frozen"), comme pour les effets du jeu (voir Le monde et les joueurs). En 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 fait émettre au bloc un signal aussi fort que son état power, un nombre de 0 à 15 ajouté automatiquement. b.set_state("power", 15) l'allume, et les fils, lampes et portes autour suivent. block.redstone_power est la puissance que le bloc reçoit de son entourage, et on_neighbor_change s'exécute quand elle change (la lampe ci-dessus l'utilise).

En Kotlin : redstone = true et block.redstonePower.

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

Inventaires

content/crate.craftCraftScript
block "crate" { texture: "minecraft:block/barrel_side", inventory: 27 }

inventory: 27 donne au bloc autant d'emplacements (de 9 à 54, par rangées de 9). Il garde ses objets d'un redémarrage à l'autre, l'utiliser ouvre un écran de coffre (sauf si son on_use a pris le clic), et le casser fait tomber son contenu. De 1 à 8 emplacements, il n'y a pas d'écran : c'est le mod qui y met et en retire les objets.

Dans le code, block.inventory (qui marche aussi pour les coffres et tonneaux du jeu) propose set(slot, item(…)), get(slot), count(id) et add(…). En Kotlin : inventory = 27.

content/Crate.ktKotlin
block("crate") {
    texture = "minecraft:block/barrel_side"
    inventory = 27
}

Objets montrés sur un bloc. shows_item: 14 fait flotter et tourner au-dessus du bloc l'objet de son premier emplacement, à ce nombre de pixels au-dessus de sa base. Tous les joueurs le voient, et il disparaît quand l'emplacement se vide ou que le bloc est cassé. Un piédestal prend l'objet que le joueur tient en main et le lui rend :

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) met un objet dans la main principale du joueur, ou la vide avec null. En Kotlin : showsItem = 14 et 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
    }
}

Textures

Les textures sont livrées dans le mod ; personne n’a besoin d’installer un pack de ressources. Le nom du fichier est l’id :

Mod Où
CraftScript (dossier) 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

Si un mod fournit ses propres modèles, recettes ou tables de butin dans ces mêmes dossiers, Crafting les utilise.

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

Les ids. Sans espace de noms, un id appartient à ton mod ("ruby" est rubies:ruby). Pour le contenu du jeu, écris l’espace de noms : "minecraft:diamond". Tu ne peux pas enregistrer de contenu dans l’espace de noms minecraft.