API
Events
Ein Event beschreibt etwas, das im Spiel passiert ist: Ein Spieler ist beigetreten, ein Block wurde abgebaut, etwas hat Schaden genommen. Es beschreibt nicht, welcher interne Code des Spiels gelaufen ist, deshalb funktioniert eine Mod, die auf join hört, weiter, auch wenn sich dieser Code ändert.
Auf ein Event hören
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)
}
}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 stehen die Eigenschaften des Events als Variablen zur Verfügung (player, block…) oder über den Namen, den du ihm gibst (on break(e)). Du kannst auf jedes Event aus beliebig vielen Dateien hören: Leg jede Regel in die Datei ihres Themas.
Alle Events
Alle werden im echten Spiel ausgelöst, je nachdem auf dem Client oder dem Server. In CraftScript kannst du den kurzen oder den langen Namen in snake_case benutzen (join oder player_join).
| CraftScript | Kotlin | Eigenschaften | Abbrechbar |
|---|---|---|---|
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 | Ja |
respawn |
PlayerRespawnEvent |
player, location | |
death |
PlayerDeathEvent |
player, death_message, keep_inventory | |
interact |
PlayerInteractBlockEvent |
player, block, hand, item | Ja |
interact_entity |
PlayerInteractEntityEvent |
player, entity, hand, item | Ja |
attack |
PlayerAttackEvent |
player, target | Ja |
key |
PlayerKeyEvent |
player, key | |
use_item |
PlayerUseItemEvent |
player, item, hand | Ja |
command |
PlayerCommandEvent |
player, command | Ja |
break |
BlockBreakEvent |
player (kann null sein), block, drop_items | Ja |
place |
BlockPlaceEvent |
player (kann null sein), block, placed | Ja |
spawn |
EntitySpawnEvent |
entity | Ja |
damage |
EntityDamageEvent |
entity, damage_type, amount (änderbar), attacker | Ja |
entity_death |
EntityDeathEvent |
entity, drops | |
hit |
ProjectileHitEvent |
projectile, shooter, entity or block | Ja |
ready |
ModsLoadedEvent |
mod_ids | |
plugin_reload |
PluginReloadEvent |
plugin_id |
Ändern, was passiert
Manche Eigenschaften lassen sich ändern, und das Spiel folgt ihnen:
| Event | Eigenschaft | Wirkung |
|---|---|---|
chat |
message |
Der Spieler sagt den neuen Text. |
command |
command |
Der neue Befehl läuft, als dieser Spieler. |
join, quit |
join_message, quit_message |
Wird allen angekündigt, zusätzlich zur Meldung des Spiels. |
respawn |
location |
Der Spieler erscheint dort wieder. |
break |
drop_items = false |
Der Block lässt nichts fallen. |
damage |
amount |
Der erlittene Schaden ist der neue Wert. |
entity_death |
drops.add(…) |
Die hinzugefügten Gegenstände fallen dort, wo es gestorben ist, zusätzlich zur normalen Beute. |
on entity_death(e) {
if e.entity.type == "minecraft:zombie" and chance(0.05) {
e.drops.add(item("rubies:ruby", 1))
}
}interact_entity ist ein Rechtsklick auf eine Entität: Wird er abgebrochen, passiert nichts (kein Melken, Handeln oder Reiten). attack ist ein Spieler, der eine Entität schlägt: Wird es abgebrochen, gibt es keinen Treffer. damage liefert attacker, wer hinter dem Schaden steckt: der Angreifer oder der Schütze eines Projektils. key läuft, wenn ein Spieler eine Taste einer Mod drückt (siehe Oberfläche).
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() }
}Noch nicht umgesetzt. In death hat das Ändern von death_message oder keep_inventory noch keine Wirkung. Crafting warnt einmal im Log davor, statt es stillschweigend zu ignorieren.
Priorität und Abbrechen
Reihenfolge: highest, high, normal, low, lowest und monitor. Bricht ein Listener das Event ab, laufen die folgenden nicht mehr, außer monitor-Listenern (und in Kotlin denen, die ignoreCancelled = true übergeben). Ein monitor-Listener beobachtet nur: Er darf das Event nicht ändern.
on damage(e) priority high {
if e.damage_type == "minecraft:fall" {
e.amount = e.amount / 2 // sanftere Landungen
}
}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}")
}
}
}Wenn etwas schiefgeht
- Ein Listener, der einen Fehler wirft, wird mit dem Namen seiner Mod geloggt, und die anderen Listener laufen weiter.
/crafting profile(zweimal: starten, dann ansehen) zeigt, wie viel Zeit jede Mod in ihren Events verbringt.- Ein Event, auf das niemand hört, wird gar nicht erst erzeugt, also kostet es nichts, auf wenige Events zu hören.