API

Sounds and particles

Custom sounds and particles ship inside the mod, like textures, and you use them by id just like the game's own. You declare them like the rest of the content.

Sounds

content/sounds.craftCraftScript
sound "ruby_chime" { file: "ruby/chime", subtitle: "A ruby chimes", pitch: 1.2 }

sound "ruby_crumble" { files: ["ruby/crumble_1", "ruby/crumble_2"], subtitle: "Ruby ore crumbles", volume: 0.8 }
Property Values Default
file file path without extension: ruby/chime is the mod's sounds/ruby/chime.ogg sounds/<id>.ogg
files several paths; one plays at random each time —
subtitle what shows when subtitles are on —
volume 0–1 1
pitch pitch; 1 is the original 1

It plays like any game sound: player.play_sound("rubies:ruby_chime") for one player, world().play_sound(location, "rubies:ruby_chime") at a location. Files are .ogg.

Particles

content/particles.craftCraftScript
particle "ruby_spark" { textures: ["ruby_spark_0", "ruby_spark_1"], motion: "sparkle" }
Property Values Default
textures images from textures/particle/, without extension. Several form an animation, in that order textures/particle/<id>.png
motion float_up: rises and fades. flame: almost still, shrinks. sparkle: drifts and twinkles. drift: floats in place. float_up

You spawn it by id: world().spawn_particle("rubies:ruby_spark", location, 30, 1.5, 0.02), with count, spread and speed like the game's particles. To send one particle a given way, pass a velocity instead: world().spawn_particle("minecraft:end_rod", location, vector(0, 0.1, 0)), in blocks per tick. Particles that are drawn toward a place, like minecraft:enchant, start at location + velocity and fly to the location.

A real use

In the example mod, when an ore drops an extra ruby, the chime plays and sparks fly where the block was:

events/mining.craftCraftScript
import { give_rubies } from "/lib/rewards"
import { SETTINGS } from "/settings"

on break(e) {
    let p = e.player
    if p == null { return }
    if e.block.type == "minecraft:diamond_ore" and chance(SETTINGS["bonus_chance"]) {
        give_rubies(p, 1)
        p.play_sound("rubies:ruby_chime")
        p.world.spawn_particle("rubies:ruby_spark", e.block.location, 12, 0.4, 0.02)
    }
}

In Kotlin

content/Sounds.ktKotlin
package com.example.rubies.content

object Sounds {
    const val CHIME = "rubies:ruby_chime"

    fun register(content: ContentBuilder) {
        content.sound("ruby_chime") { file("ruby/chime"); subtitle = "A ruby chimes"; pitch = 1.2f }
        content.sound("ruby_crumble") { file("ruby/crumble_1"); file("ruby/crumble_2"); subtitle = "Ruby ore crumbles"; volume = 0.8f }
    }
}
content/Particles.ktKotlin
package com.example.rubies.content

object Particles {
    const val SPARK = "rubies:ruby_spark"

    fun register(content: ContentBuilder) {
        content.particle("ruby_spark") { texture("ruby_spark_0"); texture("ruby_spark_1"); motion = ParticleMotion.SPARKLE }
    }
}

sound(id) { file(...); subtitle; volume; pitch } and particle(id) { texture(...); motion = ParticleMotion.SPARKLE } inside the ContentBuilder. To play and spawn: player.playSound(id), world.playSound(at, id), world.spawnParticle(id, at, count, spread, speed) and world.spawnParticle(id, at, Vector(0.0, 0.1, 0.0)).

Files

Mod Where
CraftScript (folder) mods/rubies/sounds/ruby/chime.ogg, mods/rubies/textures/particle/ruby_spark_0.png
Kotlin or Java src/main/resources/assets/rubies/sounds/ruby/chime.ogg, …/assets/rubies/textures/particle/ruby_spark_0.png