API

블록, 아이템, 조합법

콘텐츠는 속성 목록으로 선언합니다. Crafting이 알맞은 시점에 실제 게임 객체를 만들고, 필요한 모델, 전리품 테이블, 태그, 조합법, 번역을 생성합니다. 게임 데이터 파일은 하나도 작성하지 않습니다.

아이템

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" }
속성 값 기본값
stack 또는 max_stack 1–99 64
rarity common, uncommon, rare, epic(이름 색상) common
glint 마법 부여 반짝임 false
durability 숫자. stack: 1을 강제합니다 0
fireproof 용암이나 불에 타지 않습니다 false
food 숫자, 또는 { nutrition, saturation, always_edible } —
tool "pickaxe", 또는 { type, tier, damage, speed }. type: pickaxe, axe, shovel, hoe, sword —
tab 크리에이티브 인벤토리 탭(아래 참고) ingredients
texture 텍스처 경로 item/<id>
on_use fun(player, stack). 사용을 처리했다면 true를 반환합니다 —
armor { slot, defense, toughness, knockback_resistance, texture } —
on_hit fun(attacker, target, stack) —
cooldown 초 0

방어구, 무기, 쿨다운

armor가 있는 아이템은 착용할 수 있습니다. slot은 head, chest, legs, feet 중 하나입니다. defense, toughness, knockback_resistance(0~1)는 게임의 방어구 값입니다. 철 흉갑은 방어 6, 다이아몬드는 강인함 2입니다.

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는 착용했을 때의 모습입니다. frost는 모드의 textures/entity/equipment/humanoid/frost.png, 다리용으로는 textures/entity/equipment/humanoid_leggings/frost.png를 뜻하며, 게임의 방어구 텍스처와 배치가 같습니다. 없으면 철 방어구처럼 보입니다.

on_hit는 플레이어든 몹이든 그 아이템으로 때릴 때 실행됩니다.

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(초)은 on_use가 처리한 사용 뒤마다 그 시간 동안 아이템을 쓸 수 없게 하며, 핫바에 표시됩니다. 코드에서는 player.set_cooldown("minecraft:feather", 2)와 player.has_cooldown(id)를 씁니다. Kotlin에서는 방어구는 armor(EquipmentSlot.HEAD, defense = 3, texture = "frost"), 무기는 onHit = { ctx -> … }(ctx.attacker, ctx.target, ctx.stack)입니다.

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

블록

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] }
속성 값 기본값
hardness 숫자. -1 = 부술 수 없음 1.5
resistance 폭발 저항 = hardness
light 0–15 0
light_when "lit" 같은 토글 상태: 켜져 있는 동안에만 블록이 빛납니다(블록 상태 참고) 항상
sound stone, wood, gravel, grass, metal, glass, wool, sand stone
like 같은 방식으로 만들 블록. 게임의 것("minecraft:end_stone")이든 여러분의 것이든, 단단함, 저항, 소리, 무언가를 떨어뜨리려면 알맞은 도구가 필요한지가 그 블록의 것이 됩니다 —
kind 게임의 종류 중 하나: 계단, 문, 상자, 작물… (블록 종류 참고) cube
tool, tier 블록이 무언가를 떨어뜨리는 데 필요한 도구와 그 도구의 최소 재질: wood, stone, iron, diamond, netherite —, wood
drops, drop_count 아이템 하나: id. 숫자 또는 [min, max] 블록 자신, 1
loot 여러 아이템: [{ item, count, chance, tool, fortune }, …]. 각각 따로 추첨됩니다. count는 숫자 또는 [min, max], chance는 0에서 1까지(기본값 1). tool과 fortune: 아래의 드롭 참고 —
friction 보통 0.6, 얼음 0.98 0.6
transparent 너머가 보입니다(유리, 나뭇잎) false
has_item 블록의 아이템도 등록합니다. 아이템이 없으면 drops나 loot로 지정하지 않는 한 블록은 아무것도 떨어뜨리지 않습니다 true
tab 크리에이티브 인벤토리 탭 building_blocks
on_use fun(player, block). 사용을 처리했다면 true를 반환합니다. 웅크린 채 손에 무언가를 든 플레이어는 게임의 블록처럼 대신 그것을 설치합니다 —

탭: building_blocks, colored_blocks, natural_blocks, functional_blocks, redstone_blocks, tools_and_utilities, combat, food_and_drinks, ingredients, spawn_eggs. Kotlin에서는 CreativeTabs에 있습니다.

몹이 죽을 때 무언가를 더 떨어뜨리게 하려면 entity_death 이벤트에서 e.drops에 추가하세요(이벤트 참고).

정육면체가 아닌 블록, 게임 종류의 블록, 몹, 광석, 소리, 입자도 같은 방식으로 선언하며, 각각 전용 페이지가 있습니다: 블록 모양, 블록 종류, 몹, 월드 생성, 소리와 입자.

드롭: 도구와 행운

loot의 드롭에는 도구가 필요하게 할 수 있고, 행운으로 더 많이 얻게 할 수 있습니다:

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": 블록을 섬세한 손길로 부술 때만 떨어집니다. tool: "shears": 게임의 나뭇잎과 덩굴이 자신을 떨어뜨리는 것처럼, 가위나 섬세한 손길일 때만 떨어집니다.
  • 도구가 필요한 드롭이 있으면, 도구가 필요 없는 드롭은 그 도구를 쓰지 않았을 때만 일어납니다. 위의 광석은 섬세한 손길로는 자신을, 그렇지 않으면 루비를 떨어뜨립니다.
  • fortune: true: 행운이 더 많이 얻게 합니다. 게임의 광석처럼 count가 늘거나, 나뭇잎에서 나오는 묘목처럼 chance가 좋아집니다.

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

조합법

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 }

사용 동작

on_use는 데이터 옆에 놓이는 유일한 로직입니다. 두어 줄을 넘어가면 함수를 lib/에 작성하고 가져오세요.

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
}

반응하는 블록

블록은 자신이나 주변에 무언가 일어날 때 코드를 실행할 수 있습니다. 각 핸들러는 블록과, 해당하는 경우 엔티티를 받습니다.

속성 실행되는 때
on_step: fun(block, entity) 엔티티가 블록 위를 걸을 때.
on_inside: fun(block, entity) 엔티티가 블록 안에 있을 때. 블록은 엔티티가 통과할 수 있어야 합니다(포털, 식물, 단단하지 않은 모양).
on_random_tick: fun(block) 작물이 자라듯 이따금 무작위로: 블록당 약 68초에 한 번.
on_tick: fun(block) block.schedule(ticks)로 요청한 시간이 지났을 때(20틱 = 1초).
on_neighbor_change: fun(block) 옆 블록이 바뀌었을 때: 설치되거나, 부서지거나, 신호를 받았을 때.
on_placed: fun(block, entity) 누군가 블록을 설치했을 때. entity는 설치한 쪽.
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) }
}

Kotlin에서 핸들러는 onStep, onInside, onRandomTick, onTick, onNeighborChange, onPlaced입니다. 각각 block과, 있는 경우 entity를 가진 BlockEventContext를 받습니다:

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

포털

portal이 있는 블록은 안에 있는 대상을 다른 차원으로 보냅니다. 갈 차원을 지정하거나, to와 back으로 그곳에서 어디로 이어지는지 고르세요:

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

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

엔티티는 같은 x와 z의 지면에 도착하고, 그곳에서 돌아올 포털 블록을 찾습니다. 근처에 없으면 도착 지점 옆에 하나가 설치됩니다. 엔티티는 포털을 다시 쓰기 전에 잠시 기다립니다. 포털 블록은 엔티티를 통과시킵니다. 차원 자체는 dimension으로 선언합니다(@dim@ 참조). Kotlin에서:

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

블록 상태

states는 블록이 기억하고 보여줄 수 있는 값을 줍니다:

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": 북, 동, 남, 서. 블록을 설치한 플레이어를 향하며, 모델도 함께 회전합니다.
  • "lit": 이름만 쓰면 켜기/끄기 토글이며 기본값은 꺼짐입니다. { lit: true }는 기본값을 켜짐으로 합니다.
  • { stage: 3 }: 0부터 지정한 최댓값(1~15)까지의 숫자.
  • "facing_all": "facing"과 같지만 위와 아래도 향합니다. 블록을 설치한 플레이어를 향하며, 위와 아래일 때는 모델이 눕혀집니다.
  • { shape: ["top", "middle", "bottom"] }: 몇 가지 이름 중 하나이며, 첫 번째가 기본값입니다. 이름은 소문자, 숫자, _로 씁니다.

block.state("lit")로 읽고 block.set_state("lit", true)로 바꿉니다. 게임의 블록에서도 작동합니다(예: 화로의 facing과 lit).

기본값에서 벗어난 상태는 다르게 보일 수 있습니다. 텍스처는 textures/block/<id>_<이름>.png(켜진 토글) 또는 <id>_<이름><n>.png(숫자) 또는 <id>_<값>.png(이름)에, 모델은 models/block/<id>_<이름>.json에 두세요. 전체 조합(<id>_lit_stage2)을 먼저 시도하고, 그다음 각 상태를 하나씩 시도합니다. 예제에서 lamp.json과 lamp_lit.json은 모드의 두 모델이며, 예를 들어 부모를 minecraft:block/orientable로 하고 앞면, 옆면, 윗면 텍스처를 씁니다.

상태에 따른 빛. light_when: "lit"를 지정하면 블록의 light는 그 토글이 켜져 있는 동안에만 빛납니다. 램프처럼요:

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

Kotlin에서는 facing(), facingAll(), toggle("lit"), number("stage", 3), choice("shape", "top", "middle", "bottom"), 코드에서는 block.state(…)와 block.setState(…):

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

효과

모드는 자체 상태 효과를 추가할 수 있습니다. 게임의 효과처럼 플레이어 화면에 표시되며, 같은 방식으로 부여하고 확인합니다.

content/frozen.craftCraftScript
effect "frozen" {
    color: "#88CCFF"
    kind: "harmful"
    on_tick: fun(e, level) { e.damage(level) }
}
  • color: 입자와 아이콘 배경의 색.
  • kind: beneficial, harmful, neutral 중 하나.
  • on_tick: fun(e, level). 엔티티가 그 효과를 가지고 있는 동안 매초 실행되며, 레벨(1이 I)을 받습니다.
  • 아이콘은 모드의 textures/mob_effect/<id>.png입니다.

부여는 e.add_effect("mymod:frozen", 3, 1)(id, 초, 레벨), 확인은 e.has_effect("mymod:frozen")로, 게임의 효과와 같습니다(월드와 플레이어 참고). Kotlin에서:

content/Frozen.ktKotlin
content.effect("frozen") {
    color = 0x88CCFF
    kind = EffectKind.HARMFUL
    onTick = { e, level -> /* … */ }
}

레드스톤

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는 블록이 power 상태(자동으로 추가되는 0~15의 숫자)만큼 강한 신호를 내게 합니다. b.set_state("power", 15)로 켜면 주변의 전선, 램프, 문이 따라 움직입니다. block.redstone_power는 블록이 주변에서 받는 세기이며, 이것이 바뀌면 on_neighbor_change가 실행됩니다(위의 램프가 이를 씁니다).

Kotlin에서: redstone = true와 block.redstonePower.

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

인벤토리

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

inventory: 27은 블록에 그만큼의 슬롯(954, 한 줄에 9칸)을 줍니다. 아이템은 재시작 후에도 유지되고, 사용하면 상자 화면이 열리며(on_use가 클릭을 처리한 경우 제외), 부수면 들어 있던 것이 떨어집니다. 슬롯이 18개이면 화면은 없고, 모드가 직접 아이템을 넣고 꺼냅니다.

코드에서는 block.inventory(게임의 상자와 통에서도 작동)가 set(slot, item(…)), get(slot), count(id), add(…)를 제공합니다. Kotlin에서: inventory = 27.

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

블록 위에 보이는 아이템. shows_item: 14를 지정하면 블록의 첫 번째 슬롯에 있는 아이템이 블록 바닥에서 그만큼의 픽셀 위에 떠서 회전합니다. 모든 플레이어에게 보이며, 슬롯이 비거나 블록이 부서지면 사라집니다. 받침대는 플레이어가 손에 든 아이템을 받고 돌려줍니다:

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)은 플레이어의 주로 쓰는 손에 아이템을 넣으며, null이면 비웁니다. Kotlin에서: showsItem = 14와 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
    }
}

텍스처

텍스처는 모드 안에 담기므로 아무도 리소스 팩을 설치할 필요가 없습니다. 파일 이름이 id입니다.

모드 위치
CraftScript(폴더) mods/rubies/textures/item/ruby.png, mods/rubies/textures/block/ruby_ore.png
Kotlin 또는 Java src/main/resources/assets/rubies/textures/item/ruby.png

모드가 같은 폴더에 자체 모델, 조합법, 전리품 테이블을 담고 있으면 Crafting은 그것을 사용합니다.

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

id. 네임스페이스가 없는 id는 내 모드에 속합니다("ruby"는 rubies:ruby). 게임 콘텐츠에는 네임스페이스를 적으세요: "minecraft:diamond". minecraft 네임스페이스에는 콘텐츠를 등록할 수 없습니다.