API
Мир и игроки
Читай и меняй блоки, создавай сущности, общайся с игроками. В CraftScript имена пишутся в snake_case (block_at, max_health); в Kotlin и Java — в camelCase (blockAt, maxHealth). Это одни и те же объекты.
Пример
command beacon requires "rubies.beacon" describe "Зажечь маяк там, где ты стоишь" {
if player == null { return "Только для игроков" }
let w = player.world
let at = player.location
w.set_block(at.block_x, at.block_y, at.block_z, "minecraft:lantern", { hanging: false })
w.spawn_particle("minecraft:flame", at, 30, 0.5, 0.02)
w.play_sound(at, "minecraft:block.lantern.place")
player.title("&eЗажжено", "")
}object BeaconCommand {
fun register() {
Crafting.commands.command("beacon") {
permission = "rubies.beacon"
executes { c ->
val at = c.player.location
val world = c.player.world
world.setBlock(at.blockX, at.blockY, at.blockZ, Identifier.parse("minecraft:lantern"), mapOf("hanging" to false))
world.spawnParticle(Identifier.parse("minecraft:flame"), at, count = 30, spread = 0.5, speed = 0.02)
world.playSound(at, Identifier.parse("minecraft:block.lantern.place"))
c.player.title("&eЗажжено")
}
}
}
}Мир
world() в CraftScript (основной мир или world("minecraft:the_nether")); Crafting.server?.world(id) или player.world в Kotlin.
| Член | Что делает |
|---|---|
id, players, time, is_raining, data |
Id мира, игроки, время суток (чтение и запись), идёт ли дождь, сохранённые данные. |
block_at(x, y, z) |
Блок в этой позиции. |
set_block(x, y, z, type) |
Ставит блок. |
set_block(x, y, z, type, states) |
Ставит блок с состояниями: { open: true }, { facing: "north" }. |
spawn(type, location) |
Создаёт сущность. |
drop_item(location, stack) |
Бросает предмет на землю. |
explode(location, power, fire?) |
Взрыв. |
strike_lightning(location) |
Удар молнии. |
spawn_particle(id, location, count?, spread?, speed?) |
Частицы. |
spawn_particle(id, location, velocity) |
Одна частица, летящая с этой скоростью, в блоках за тик. Некоторые, как minecraft:enchant и minecraft:portal, летят к месту, где они созданы: они появляются в location + velocity. |
play_sound(location, id, volume?, pitch?) |
Звук в точке. |
light_at(x, y, z) |
Сколько там света, от 0 до 15. |
container_at(x, y, z) |
Инвентарь сундука, бочки… или null. |
set_sign_text(x, y, z, lines) |
Текст на табличке. |
set_chunk_loaded(cx, cz, loaded) |
Держит чанк загруженным, даже если рядом никого нет. |
entities() |
Сущности в мире. |
living_near(location, radius) |
Живые сущности возле места, от ближайшей к дальней. |
shoot(projectile, from, velocity, shooter?, damage?) |
Запускает снаряд игры или мода. |
Игрок
| Член | Что делает |
|---|---|
name, uuid, is_op, has_crafting_client |
Данные игрока; установлен ли на клиенте Crafting. |
send(msg), action_bar(msg), title(title, subtitle?) |
Сообщения в чате, на панели действий и на экране. Цвета через &. |
inventory, held_item, give(stack) |
Инвентарь, предмет в руке, выдать предмет. |
set_held_item(stack) |
Кладёт предмет в основную руку вместо того, что там было; null опустошает руку. |
health, max_health, food_level, game_mode |
Здоровье, голод (чтение и запись) и режим игры. |
is_sleeping |
Спит ли игрок. |
data |
Данные, сохранённые вместе с игроком (ниже). |
play_sound(id, volume?, pitch?) |
Звук только для этого игрока. |
has_permission(p), kick(reason) |
Права; выгнать с сервера. |
Player — это ещё и живая сущность (ниже).
Сущности, блоки и инвентари
| Тип | Члены |
|---|---|
| Entity | uuid, type, world, location, custom_name, is_alive, data, direction, vehicle; teleport, remove, set_rotation, add_tag, has_tag. |
| LivingEntity | Всё из Entity, плюс health, max_health; damage, heal, set_ai, add_effect, remove_effect, has_effect, effects, add_modifier, remove_modifier, attribute, set_attribute, equipment, set_equipment (выключает или включает её собственное поведение). |
| Block | type, x, y, z, world, location, is_solid, data; set_type, relative(dx, dy, dz). |
| Inventory | size; get(slot), set(slot, stack), add(stack), count(id), clear(). |
| Location | world, x, y, z, yaw, pitch, block_x, block_y, block_z; add(dx, dy, dz), distance_to(other). |
ItemStack содержит id, количество, название, описание (lore) и собственные данные мода и сохраняет их, перемещаясь по инвентарям и сундукам. В CraftScript он создаётся через item("rubies:ruby", 3); в Kotlin — через ItemStack.of("rubies:ruby", 3) или полный конструктор.
stack.enchantments — это словарь из id каждого зачарования в его уровень (minecraft:sharpness → 3); у зачарованной книги это те зачарования, которые она даёт. В Kotlin stack.withEnchantments(mapOf(Identifier.parse("minecraft:sharpness") to 3)) — тот же стек с этими зачарованиями. Стек, прочитанный из игры, сохраняет всё, что у него есть, в том числе то, чего API не называет (содержимое карты, эффекты зелья), когда мод перемещает его или меняет через with_count или withEnchantments (copy в Kotlin этого не сохраняет).
Эффекты, атрибуты и экипировка
Эффекты. У любой живой сущности могут быть эффекты игры. e.add_effect("minecraft:speed", 8, 3) принимает id, секунды и уровень (1 — это I); необязательный последний аргумент, true или false, задаёт, показывать ли частицы. Дополняют это remove_effect(id), has_effect(id) и effects (словарь из id в { level, seconds }). В Kotlin: addEffect(Identifier.parse("minecraft:speed"), 8.0, 3) и ActiveEffect(level, seconds).
Мод может объявлять собственные эффекты (см. Блоки, предметы и рецепты); они накладываются и проверяются теми же членами.
Атрибуты. attribute("minecraft:movement_speed") возвращает текущее значение с учётом брони и эффектов. set_attribute("minecraft:scale", 1.6) меняет базовое значение: scale, attack_damage, max_health, jump_strength, armor… В Kotlin: attribute(id) и setAttribute(id, value).
command grow() {
let p = player
if p.attribute("minecraft:scale") > 1.2 { p.set_attribute("minecraft:scale", 1) } else { p.set_attribute("minecraft:scale", 1.6) }
}Модификаторы. Модификатор изменяет атрибут, не заменяя его базовое значение, поэтому несколько модификаторов суммируются, и каждый можно убрать. e.add_modifier("minecraft:movement_speed", "mymod:frozen_slow", -0.3, "percent_of_base") принимает атрибут, id модификатора, величину и операцию; e.remove_modifier("minecraft:movement_speed", "mymod:frozen_slow") убирает его. Повторное добавление с тем же id заменяет его. Операции: add (прибавляет величину), percent_of_base (прибавляет величину, умноженную на базовое значение) и multiply_total (умножает результат на 1 плюс величина). На Kotlin: addModifier(attr, id, amount, ModifierOperation.PERCENT_OF_BASE).
command chill() {
player.add_modifier("minecraft:movement_speed", "mymod:chill", -0.3, "percent_of_base")
// later: player.remove_modifier("minecraft:movement_speed", "mymod:chill")
}Езда и эффекты по области. entity.vehicle — это то, на чём едет сущность, или null. world.living_near(location, radius) перечисляет живые сущности вокруг места, от ближайшей к дальней, а это то, что нужно эффектам по области:
command frostwave() {
let p = player
for other in p.world.living_near(p.location, 8) {
if other.type != "minecraft:player" { other.add_effect("mymod:frozen", 4, 1) }
}
}Экипировка. e.equipment("head") — предмет, надетый в этот слот, или null; e.set_equipment("main_hand", item("minecraft:iron_sword")) его меняет. Слоты: main_hand, off_hand, head, chest, legs и feet. В Kotlin: EquipmentSlot.HEAD, equipment(slot) и setEquipment(slot, stack).
Направление и перезарядка. entity.direction — куда смотрит сущность, вектор длиной в один блок. player.set_cooldown(item, seconds) и player.has_cooldown(item) ставят предмет на перезарядку и проверяют её.
Сохранённые данные
У игроков, сущностей, блоков и миров есть data: хранилище «ключ — значение», которое переживает перезапуски. В нём хранятся строки, числа, логические значения, списки и словари.
// Data that survives restarts. Keys start with the mod id: they're shared by every mod.
const VISITS = "rubies.visits"
fun visits(p: Player): number {
return p.data.get_int(VISITS) ?? 0
}
fun add_visit(p: Player): number {
let n = visits(p) + 1
p.data.set(VISITS, n)
return n
}package com.example.rubies.storage
object Visits {
private const val KEY = "rubies.visits" // shared by every mod: prefix it with the mod id
fun of(player: Player): Int = player.data.getInt(KEY) ?: 0
fun add(player: Player): Int = (of(player) + 1).also { player.data[KEY] = it }
}| CraftScript | Kotlin / Java | Что делает |
|---|---|---|
data.set(k, v) или data[k] = v |
data[k] = v |
Сохраняет значение (null удаляет его). |
data[k] |
data[k] |
Читает значение в том виде, как оно было сохранено, или null. |
data.get_int(k), get_number, get_string, get_boolean |
getInt(k), getNumber, getString, getBoolean |
Читает значение этого типа или null, если его нет. |
data.remove(k), data.clear(), data.keys |
remove(k), clear(), keys |
Удаляет ключ, удаляет всё, перечисляет ключи. |
- Ключи общие для всех модов. Начинай каждый ключ с id своего мода (
rubies.visits), чтобы не перезаписать ключи другого мода. - Сколько они живут: данные игрока остаются с игроком; данные сущности исчезают, когда она погибает; данные блока исчезают, когда игрок его ломает или когда его заменяют через API.
- Числа хранятся как дробные;
get_intвозвращает их как целые. - Держи ключи и их функции в одном файле (
lib/storage.craft,storage/в Kotlin): остальному моду не нужно их знать. Смотри Как организовать мод.
Сервер
| Член | Что делает |
|---|---|
players, worlds, motd, tps, is_dedicated |
Состояние сервера; tps — среднее число тиков в секунду (идеал — 20). |
player(name), world(id) |
Найти игрока в сети или мир. |
broadcast(msg) |
Сообщение всем. |
stop() |
Сохраняет и останавливает сервер. |
run_command(cmd) |
Запасной выход: выполняет игровую команду (смотри ниже). |
Запасные выходы
Две функции принимают собственные форматы игры: run_command (run(…) в CraftScript), которая выполняет игровую команду, и summon(type, location, nbt), которая создаёт сущность с данными во внутреннем формате игры. Они существуют для того, что API пока не покрывает, но эти форматы принадлежат Minecraft и могут измениться в новой версии, поэтому мод, который от них зависит, может сломаться. Используй их как можно реже и всегда предпочитай API.
Ничего выдуманного. Ни один член API не возвращает значение-заглушку. Если что-то не может работать в запущенной игре, выбрасывается ошибка, которая говорит, что и почему.