API

Eventi

Un evento descrive qualcosa che è successo nel gioco: un giocatore è entrato, un blocco si è rotto, qualcosa ha subito danni. Non descrive quale codice interno del gioco è stato eseguito, ed è per questo che una mod che ascolta join continua a funzionare anche quando quel codice cambia.

Ascoltare un 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)
            }
        }
    }
}

In CraftScript, le proprietà dell’evento sono disponibili come variabili (player, block…) o tramite il nome che gli dai (on break(e)). Puoi ascoltare ogni evento da quanti file vuoi: metti ogni regola nel file del suo tema.

Tutti gli eventi

Vengono tutti emessi nel gioco vero, sul client o sul server a seconda del caso. In CraftScript puoi usare il nome breve o quello lungo in snake_case (join o player_join).

CraftScript Kotlin Proprietà Annullabile
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 Sì
respawn PlayerRespawnEvent player, location
death PlayerDeathEvent player, death_message, keep_inventory
interact PlayerInteractBlockEvent player, block, hand, item Sì
interact_entity PlayerInteractEntityEvent player, entity, hand, item Sì
attack PlayerAttackEvent player, target Sì
key PlayerKeyEvent player, key
use_item PlayerUseItemEvent player, item, hand Sì
command PlayerCommandEvent player, command Sì
break BlockBreakEvent player (può essere null), block, drop_items Sì
place BlockPlaceEvent player (può essere null), block, placed Sì
spawn EntitySpawnEvent entity Sì
damage EntityDamageEvent entity, damage_type, amount (modificabile), attacker Sì
entity_death EntityDeathEvent entity, drops
hit ProjectileHitEvent projectile, shooter, entity or block Sì
ready ModsLoadedEvent mod_ids
plugin_reload PluginReloadEvent plugin_id

Cambiare ciò che succede

Alcune proprietà si possono modificare, e il gioco ne tiene conto:

Evento Proprietà Effetto
chat message Il giocatore dice il nuovo testo.
command command Viene eseguito il nuovo comando, come quel giocatore.
join, quit join_message, quit_message Annunciato a tutti, oltre al messaggio del gioco.
respawn location Il giocatore rinasce lì.
break drop_items = false Il blocco non rilascia nulla.
damage amount Il danno subito è il nuovo valore.
entity_death drops.add(…) Gli oggetti aggiunti cadono dove è morta, oltre al suo bottino normale.
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 è un clic destro su un'entità: se lo annulli non succede nulla (niente mungitura, scambi o cavalcata). attack è un giocatore che colpisce un'entità: se lo annulli non c'è colpo. damage fornisce attacker, chi c'è dietro il danno: l'attaccante o chi ha tirato un proiettile. key viene eseguito quando un giocatore preme un tasto di una mod (vedi Interfaccia).

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

Non ancora applicato. In death, cambiare death_message o keep_inventory non ha ancora effetto. Crafting lo segnala una volta nel log invece di ignorarlo in silenzio.

Priorità e annullamento

Ordine: highest, high, normal, low, lowest e monitor. Quando un listener annulla l’evento, quelli successivi non vengono eseguiti, tranne i listener monitor (e in Kotlin quelli che passano ignoreCancelled = true). Un listener monitor si limita a osservare: non deve modificare l’evento.

events/falls.craftCraftScript
on damage(e) priority high {
    if e.damage_type == "minecraft:fall" {
        e.amount = e.amount / 2        // atterraggi più morbidi
    }
}
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 qualcosa va storto

  • Un listener che lancia un errore viene registrato nel log con il nome della sua mod, e gli altri listener continuano a funzionare.
  • /crafting profile (due volte: avvia, poi visualizza) mostra quanto tempo passa ogni mod nei suoi eventi.
  • Un evento che nessuno ascolta non viene nemmeno costruito, quindi ascoltare pochi eventi non costa nulla.