API

Eventos

Um evento descreve algo que aconteceu no jogo: um jogador entrou, um bloco quebrou, algo levou dano. Ele não descreve qual código interno do jogo rodou, e é por isso que um mod que escuta join continua funcionando mesmo quando esse código muda.

Escutando um evento

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)
    }
}
events/MiningEvents.ktKotlin
package com.example.rubies.events

object MiningEvents {
    fun register(config: RubiesConfig) {
        Crafting.events.on<BlockBreakEvent> { e ->
            val player = e.player ?: return@on
            if (e.block.type.path == "diamond_ore" && Math.random() < config.dropChance) {
                player.give(ItemStack.of(Items.RUBY))
                player.playSound(Identifier.parse(Sounds.CHIME))
                player.world.spawnParticle(Identifier.parse(Particles.SPARK), e.block.location, count = 12, spread = 0.4, speed = 0.02)
            }
        }
    }
}

Em CraftScript, as propriedades do evento estão disponíveis como variáveis (player, block…) ou pelo nome que você der a ele (on break(e)). Você pode escutar cada evento em quantos arquivos quiser: coloque cada regra no arquivo do seu tema.

Todos os eventos

Todos eles disparam no jogo real, no cliente ou no servidor, conforme o caso. Em CraftScript você pode usar o nome curto ou o longo em snake_case (join ou player_join).

CraftScript Kotlin Propriedades Cancelável
server_starting ServerStartingEvent server
start ServerStartedEvent server
stop ServerStoppingEvent server
tick ServerTickEvent server, tick, phase
client_tick ClientTickEvent tick, phase
world_load WorldLoadEvent world
world_unload WorldUnloadEvent world
join PlayerJoinEvent player, join_message
quit, leave PlayerQuitEvent player, quit_message
chat PlayerChatEvent player, message Sim
respawn PlayerRespawnEvent player, location
death PlayerDeathEvent player, death_message, keep_inventory
interact PlayerInteractBlockEvent player, block, hand, item Sim
interact_entity PlayerInteractEntityEvent player, entity, hand, item Sim
attack PlayerAttackEvent player, target Sim
key PlayerKeyEvent player, key
use_item PlayerUseItemEvent player, item, hand Sim
command PlayerCommandEvent player, command Sim
break BlockBreakEvent player (pode ser null), block, drop_items Sim
place BlockPlaceEvent player (pode ser null), block, placed Sim
spawn EntitySpawnEvent entity Sim
damage EntityDamageEvent entity, damage_type, amount (alterável), attacker Sim
entity_death EntityDeathEvent entity, drops
hit ProjectileHitEvent projectile, shooter, entity or block Sim
ready ModsLoadedEvent mod_ids
plugin_reload PluginReloadEvent plugin_id

Mudando o que acontece

Algumas propriedades podem ser alteradas, e o jogo as segue:

Evento Propriedade Efeito
chat message O jogador diz o novo texto.
command command O novo comando é executado, como esse jogador.
join, quit join_message, quit_message Anunciada a todos, além da mensagem do jogo.
respawn location O jogador renasce ali.
break drop_items = false O bloco não dropa nada.
damage amount O dano recebido passa a ser o novo valor.
entity_death drops.add(…) Os itens adicionados caem onde ela morreu, além do loot normal.
events/hunting.craftCraftScript
on entity_death(e) {
    if e.entity.type == "minecraft:zombie" and chance(0.05) {
        e.drops.add(item("rubies:ruby", 1))
    }
}

interact_entity é um clique direito numa entidade: se o cancelar, nada acontece (nem ordenhar, negociar ou montar). attack é um jogador a atingir uma entidade: se o cancelar, não há golpe. damage fornece attacker, quem está por trás do dano: o atacante ou quem disparou um projétil. key é executado quando um jogador carrega numa tecla de um mod (veja Interface).

events/entities.craftCraftScript
on interact_entity(e) {
    if e.entity.type == "minecraft:cow" { e.player.send("This cow won't be milked"); e.cancel() }
}

on attack(e) {
    if e.target.type == "minecraft:pig" { e.player.action_bar("This pig is protected"); e.cancel() }
}

Ainda não aplicado. Em death, mudar death_message ou keep_inventory ainda não tem efeito. O Crafting avisa sobre isso uma vez no log em vez de ignorar em silêncio.

Prioridade e cancelamento

Ordem: highest, high, normal, low, lowest e monitor. Quando um listener cancela o evento, os seguintes não rodam, exceto os listeners monitor (e, em Kotlin, os que passam ignoreCancelled = true). Um listener monitor só observa: ele não deve alterar o evento.

events/falls.craftCraftScript
on damage(e) priority high {
    if e.damage_type == "minecraft:fall" {
        e.amount = e.amount / 2        // quedas mais suaves
    }
}
events/ChatEvents.ktKotlin
object ChatEvents {
    fun register() {
        Crafting.events.on<PlayerChatEvent>(EventPriority.HIGHEST) { e ->
            if (e.message.startsWith("!")) e.cancel()
        }
        Crafting.events.on<PlayerChatEvent>(EventPriority.MONITOR) { e ->
            if (!e.isCancelled) Crafting.runtime.logger("chat").info("${e.player.name}: ${e.message}")
        }
    }
}

Quando algo falha

  • Um listener que lança um erro é registrado no log com o nome do seu mod, e os outros listeners continuam rodando.
  • /crafting profile (duas vezes: iniciar e depois ver) mostra quanto tempo cada mod gasta em seus eventos.
  • Um evento que ninguém escuta nem chega a ser criado, então escutar poucos eventos não custa nada.