API
O mundo e os jogadores
Leia e altere blocos, gere entidades, fale com os jogadores. Em CraftScript os nomes usam snake_case (block_at, max_health); em Kotlin e Java usam camelCase (blockAt, maxHealth). São os mesmos objetos.
Um exemplo
command beacon requires "rubies.beacon" describe "Acende um farol onde você está" {
if player == null { return "Apenas jogadores" }
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("&eAceso", "")
}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("&eAceso")
}
}
}
}Mundo
world() em CraftScript (o mundo principal, ou world("minecraft:the_nether")); Crafting.server?.world(id) ou player.world em Kotlin.
| Membro | O que faz |
|---|---|
id, players, time, is_raining, data |
Id do mundo, jogadores, hora do dia (leitura e escrita), se está chovendo, dados salvos. |
block_at(x, y, z) |
O bloco nessa posição. |
set_block(x, y, z, type) |
Coloca um bloco. |
set_block(x, y, z, type, states) |
Coloca um bloco com estados: { open: true }, { facing: "north" }. |
spawn(type, location) |
Gera uma entidade. |
drop_item(location, stack) |
Solta um item no chão. |
explode(location, power, fire?) |
Explosão. |
strike_lightning(location) |
Raio. |
spawn_particle(id, location, count?, spread?, speed?) |
Partículas. |
spawn_particle(id, location, velocity) |
Uma partícula indo com essa velocidade, em blocos por tick. Algumas, como minecraft:enchant e minecraft:portal, vão em direção ao lugar onde são geradas: vêm de location + velocity. |
play_sound(location, id, volume?, pitch?) |
Um som em uma posição. |
light_at(x, y, z) |
Quanta luz há, de 0 a 15. |
container_at(x, y, z) |
O inventário de um baú, barril…, ou null. |
set_sign_text(x, y, z, lines) |
Texto em uma placa. |
set_chunk_loaded(cx, cz, loaded) |
Mantém um chunk carregado mesmo sem ninguém por perto. |
entities() |
As entidades do mundo. |
living_near(location, radius) |
As entidades vivas perto de um ponto, da mais próxima à mais distante. |
shoot(projectile, from, velocity, shooter?, damage?) |
Lança um projétil, do jogo ou de um mod. |
Jogador
| Membro | O que faz |
|---|---|
name, uuid, is_op, has_crafting_client |
Identidade; se o cliente tem o Crafting instalado. |
send(msg), action_bar(msg), title(title, subtitle?) |
Mensagens no chat, na barra de ação e na tela. Cores com &. |
inventory, held_item, give(stack) |
Inventário, o item na mão, dar um item. |
set_held_item(stack) |
Coloca um item na mão principal, no lugar do que havia; null a esvazia. |
health, max_health, food_level, game_mode |
Vida, fome (leitura e escrita) e modo de jogo. |
is_sleeping |
Se o jogador está dormindo. |
data |
Dados salvos com o jogador (abaixo). |
play_sound(id, volume?, pitch?) |
Um som só para esse jogador. |
has_permission(p), kick(reason) |
Permissões; expulsar. |
Um Player também é uma entidade viva (abaixo).
Entidades, blocos e inventários
| Tipo | Membros |
|---|---|
| Entity | uuid, type, world, location, custom_name, is_alive, data, direction, vehicle; teleport, remove, set_rotation, add_tag, has_tag. |
| LivingEntity | Tudo de Entity mais health, max_health; damage, heal, set_ai, add_effect, remove_effect, has_effect, effects, add_modifier, remove_modifier, attribute, set_attribute, equipment, set_equipment (desliga ou liga o comportamento próprio). |
| 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). |
Um ItemStack guarda um id, uma quantidade, um nome, uma descrição (lore) e os dados do próprio mod, e os mantém enquanto passa por inventários e baús. Em CraftScript você cria um com item("rubies:ruby", 3); em Kotlin, com ItemStack.of("rubies:ruby", 3) ou com o construtor completo.
stack.enchantments é um mapa do id de cada encantamento para o seu nível (minecraft:sharpness → 3); em um livro encantado, os que ele dá. Em Kotlin, stack.withEnchantments(mapOf(Identifier.parse("minecraft:sharpness") to 3)) é o mesmo stack com esses encantamentos. Um stack lido do jogo mantém tudo o que tem, inclusive o que a API não nomeia (o conteúdo de um mapa, os efeitos de uma poção), quando um mod o move ou o altera com with_count ou withEnchantments (o copy do Kotlin não o mantém).
Efeitos, atributos e equipamento
Efeitos. Qualquer entidade viva pode ter os efeitos do jogo. e.add_effect("minecraft:speed", 8, 3) recebe o id, os segundos e o nível (1 é I); um último argumento opcional, true ou false, indica se mostra partículas. remove_effect(id), has_effect(id) e effects (um mapa de id para { level, seconds }) completam o conjunto. Em Kotlin: addEffect(Identifier.parse("minecraft:speed"), 8.0, 3) e ActiveEffect(level, seconds).
Um mod pode declarar efeitos próprios (veja Blocos, itens e receitas); eles são aplicados e consultados com esses mesmos membros.
Atributos. attribute("minecraft:movement_speed") devolve o valor atual, contando armadura e efeitos. set_attribute("minecraft:scale", 1.6) muda o valor base: scale, attack_damage, max_health, jump_strength, armor… Em Kotlin: attribute(id) e 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) }
}Modificadores. Um modificador altera um atributo sem substituir o seu valor base, então vários podem se somar e cada um pode ser removido. e.add_modifier("minecraft:movement_speed", "mymod:frozen_slow", -0.3, "percent_of_base") recebe o atributo, um id para o modificador, a quantidade e a operação; e.remove_modifier("minecraft:movement_speed", "mymod:frozen_slow") o remove. Adicionar o mesmo id de novo o substitui. As operações são add (soma a quantidade), percent_of_base (soma a quantidade vezes o valor base) e multiply_total (multiplica o resultado por 1 mais a quantidade). Em 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")
}Montaria e efeitos em área. entity.vehicle é aquilo em que a entidade está montada, ou null. world.living_near(location, radius) lista as entidades vivas ao redor de um ponto, da mais próxima à mais distante, que é do que os efeitos em área precisam:
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) }
}
}Equipamento. e.equipment("head") é o item vestido nessa posição, ou null; e.set_equipment("main_hand", item("minecraft:iron_sword")) troca-o. As posições são main_hand, off_hand, head, chest, legs e feet. Em Kotlin: EquipmentSlot.HEAD, equipment(slot) e setEquipment(slot, stack).
Direção e tempos de recarga. entity.direction é para onde olha, um vetor de um bloco de comprimento. player.set_cooldown(item, seconds) e player.has_cooldown(item) põem um item em recarga e verificam-no.
Dados salvos
Jogadores, entidades, blocos e mundos têm data: um armazenamento de chave e valor que sobrevive a reinicializações. Ele guarda strings, números, booleanos, listas e mapas.
// 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 | O que faz |
|---|---|---|
data.set(k, v) ou data[k] = v |
data[k] = v |
Guarda um valor (null o apaga). |
data[k] |
data[k] |
Lê um valor como foi guardado, ou null. |
data.get_int(k), get_number, get_string, get_boolean |
getInt(k), getNumber, getString, getBoolean |
Lê um valor desse tipo, ou null se não houver. |
data.remove(k), data.clear(), data.keys |
remove(k), clear(), keys |
Apaga uma chave, apaga tudo, lista as chaves. |
- As chaves são compartilhadas por todos os mods. Comece cada chave com o id do seu mod (
rubies.visits) para não sobrescrever as chaves de outro mod. - Quanto tempo dura: os dados de um jogador ficam com o jogador; os de uma entidade somem quando ela morre; os de um bloco somem quando um jogador o quebra ou quando ele é substituído pela API.
- Os números são guardados como decimais;
get_intos retorna como inteiros. - Coloque as chaves e suas funções em um único arquivo (
lib/storage.craft,storage/em Kotlin): o resto do mod não precisa conhecê-las. Veja Organizando um mod.
Servidor
| Membro | O que faz |
|---|---|
players, worlds, motd, tps, is_dedicated |
Estado do servidor; tps é a média de ticks por segundo (20 é o ideal). |
player(name), world(id) |
Encontra um jogador online ou um mundo. |
broadcast(msg) |
Mensagem para todos. |
stop() |
Salva e para o servidor. |
run_command(cmd) |
Saída de emergência: executa um comando do jogo (veja abaixo). |
Saídas de emergência
Duas funções aceitam os formatos do próprio jogo: run_command (run(…) em CraftScript), que executa um comando do jogo, e summon(type, location, nbt), que cria uma entidade com dados no formato interno do jogo. Elas existem para o que a API ainda não cobre, mas esses formatos pertencem ao Minecraft e podem mudar em uma nova versão, então um mod que depende deles pode quebrar. Use-as o mínimo possível e prefira sempre a API.
Nada inventado. Nenhum membro da API retorna um valor de mentira. Se algo não pode funcionar no jogo que está rodando, ele lança um erro que diz o quê e por quê.