API

イベント

イベントは、ゲームで起きたことを表します。プレイヤーが参加した、ブロックが壊れた、何かがダメージを受けた。ゲーム内部のどのコードが実行されたかは表しません。だからこそ、join を受け取る Mod は、そのコードが変わっても動き続けます。

イベントを受け取る

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

CraftScript では、イベントのプロパティは変数(player、block…)として、または付けた名前(on break(e))を通して使えます。各イベントはいくつのファイルからでも受け取れます。ルールはそれぞれのテーマのファイルに置きましょう。

すべてのイベント

すべて本物のゲームで、必要に応じてクライアントかサーバーで発生します。CraftScript では、短い名前と snake_case の長い名前のどちらも使えます(join または player_join)。

CraftScript Kotlin プロパティ キャンセル可能
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 はい
respawn PlayerRespawnEvent player, location
death PlayerDeathEvent player, death_message, keep_inventory
interact PlayerInteractBlockEvent player, block, hand, item はい
interact_entity PlayerInteractEntityEvent player, entity, hand, item はい
attack PlayerAttackEvent player, target はい
key PlayerKeyEvent player, key
use_item PlayerUseItemEvent player, item, hand はい
command PlayerCommandEvent player, command はい
break BlockBreakEvent player(null の場合あり), block, drop_items はい
place BlockPlaceEvent player(null の場合あり), block, placed はい
spawn EntitySpawnEvent entity はい
damage EntityDamageEvent entity, damage_type, amount(変更可能), attacker はい
entity_death EntityDeathEvent entity, drops
hit ProjectileHitEvent projectile, shooter, entity or block はい
ready ModsLoadedEvent mod_ids
plugin_reload PluginReloadEvent plugin_id

起きることを変える

一部のプロパティは変更でき、ゲームはそれに従います。

イベント プロパティ 効果
chat message プレイヤーが新しいテキストを発言します。
command command 新しいコマンドが、そのプレイヤーとして実行されます。
join、quit join_message、quit_message ゲームのメッセージに加えて、全員に告知されます。
respawn location プレイヤーはそこでリスポーンします。
break drop_items = false ブロックは何もドロップしません。
damage amount 受けるダメージが新しい値になります。
entity_death drops.add(…) 追加したアイテムが、通常のドロップに加えて、倒れた場所に落ちます。
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 はエンティティへの右クリックです。キャンセルすると何も起きません(乳搾り、取引、騎乗もなし)。attack はプレイヤーがエンティティを攻撃することで、キャンセルすると攻撃は当たりません。damage は attacker、つまりダメージの元(攻撃者、または飛び道具を撃った者)を返します。key はプレイヤーが Mod のキーを押したときに実行されます(インターフェースを参照)。

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

まだ反映されないもの。death で death_message や keep_inventory を変更しても、まだ効果はありません。Crafting は黙って無視するのではなく、ログに一度警告を出します。

優先度とキャンセル

順番:highest、high、normal、low、lowest、monitor。リスナーがイベントをキャンセルすると、それ以降のリスナーは実行されません。例外は monitor のリスナー(と Kotlin では ignoreCancelled = true を渡したもの)です。monitor のリスナーは観察するだけで、イベントを変更してはいけません。

events/falls.craftCraftScript
on damage(e) priority high {
    if e.damage_type == "minecraft:fall" {
        e.amount = e.amount / 2        // 着地をやわらかく
    }
}
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}")
        }
    }
}

何かが失敗したら

  • エラーを投げたリスナーは Mod の名前とともにログに記録され、他のリスナーは動き続けます。
  • /crafting profile(2 回:開始してから表示)で、各 Mod がイベントにどれだけ時間を使っているかがわかります。
  • 誰も受け取らないイベントは作られもしないので、少ないイベントを受け取るだけなら負荷はかかりません。