Event Types - HimxhMC/HimDSL GitHub Wiki

事件类型解析 / Event Type Resolution

事件类型名的写法 / How Event Names Are Written

event(TypeName) 里的 TypeName 是 Bukkit 事件的类名。常见写法有两种:

TypeName is a Bukkit event class name. Two forms:

event(PlayerJoinEvent)                          // 简单名
event(org.bukkit.event.player.PlayerJoinEvent)  // 全限定名

优先用简单名。它更短,而且 HimDSL 会在常见的包里自动查找。

Prefer the simple name — shorter, and HimDSL searches common packages automatically.


简单名的查找顺序 / Simple Name Lookup Order

给一个简单名(如 PlayerJoinEvent),HimDSL 按顺序在以下包里查找:

Given a simple name (e.g. PlayerJoinEvent), HimDSL checks these packages in order:

org.bukkit.event.player.
org.bukkit.event.block.
org.bukkit.event.entity.
org.bukkit.event.inventory.
org.bukkit.event.server.
org.bukkit.event.world.
org.bukkit.event.

找到就停,不会继续找后面的包。如果第一个匹配的是错误的类(重名情况),你可能拿到意料之外的事件。这种情况非常罕见,但存在。

Stops at the first hit. If the first match is the wrong class (a name clash), you get an unexpected event. Rare but real.


常见事件速查 / Common Events at a Glance

事件 触发时机
PlayerJoinEvent 玩家加入
PlayerQuitEvent 玩家离开
PlayerRespawnEvent 玩家重生
PlayerMoveEvent 玩家移动(高频,慎用)
PlayerCommandPreprocessEvent 玩家执行命令
PlayerDropItemEvent 玩家丢弃物品
PlayerInteractEvent 玩家右键/左键
PlayerInteractEntityEvent 玩家右键实体
BlockBreakEvent 玩家破坏方块
BlockPlaceEvent 玩家放置方块
InventoryClickEvent 点击 GUI 槽位
ServerLoadEvent 服务器加载完成
PluginEnableEvent 插件启用
PluginDisableEvent 插件禁用
SignChangeEvent 修改告示牌
Event When
PlayerJoinEvent player joins
PlayerQuitEvent player leaves
PlayerRespawnEvent player respawns
PlayerMoveEvent player moves (high frequency)
PlayerCommandPreprocessEvent player runs a command
PlayerDropItemEvent player drops an item
PlayerInteractEvent player left/right clicks
PlayerInteractEntityEvent player right-clicks an entity
BlockBreakEvent player breaks a block
BlockPlaceEvent player places a block
InventoryClickEvent player clicks a slot in an inventory
ServerLoadEvent server finishes loading
PluginEnableEvent a plugin enables
PluginDisableEvent a plugin disables
SignChangeEvent a sign is edited

这只是常用子集。完整的 Bukkit 事件列表见官方文档。

This is only a common subset. The full Bukkit event list is in the official docs.


用全限定名的时机 / When to Use a Fully-Qualified Name

三种情况:

Three cases:

情况一:简单名找不到

第三方插件的事件类不在默认包里,必须写全限定名:

Third-party plugins' events are not in default packages; use the fully-qualified name:

event("com.example.customplugin.CustomEvent")

情况二:重名

如果两个包里有同名事件,简单名只能选到先搜的那个。想指定另一个,用全限定名。

If two packages share a name, the simple name picks the first searched. Use a fully-qualified name to force the other.

情况三:明确文档意图

关键脚本建议写全限定名,读代码的人可以立刻知道是哪个类。

Critical scripts benefit from fully-qualified names; readers know exactly which class is meant.

// 简单名
event(PlayerJoinEvent)

// 全限定名,无歧义
event("org.bukkit.event.player.PlayerJoinEvent")

找不到会怎样 / What Happens If Not Found

事件类找不到时,start 会报错,指明事件类型未知:

If the class cannot be found, start errors, indicating the unknown event type:

@EventHandler
void bad(event(NotARealEvent)) {
    // ...
}

int main() {
    start("bad");       // 报错:未知事件类型
}

启动失败不会让服务器崩溃,脚本里的其他部分照常运行。查看控制台日志确认哪一行出错。

Startup failure does not crash the server; other parts continue. Check the console log for the exact line.


一个例子:命令监听 / Example: Command Listener

@EventHandler
void onCommand(event(PlayerCommandPreprocessEvent)) {
    player p = @s;
    string msg = event.getMessage();

    if (msg.startsWith("/say")) {
        runcmd("CONSOLE", "say [记录] " + p.name + " 执行了 " + msg);
    }
}

int main() {
    start("onCommand");
}

event.getMessage() 拿到玩家执行的命令文本(含前导斜杠)。这是下一章的内容。

event.getMessage() returns the command text (with leading slash). That is next chapter's topic.


小结 / Summary

  • 简单名优先,默认包按顺序查找。

  • 常见事件见上方速查。

  • 第三方事件用全限定名。

  • 重名情况下用全限定名消除歧义。

  • 找不到事件类型时 start 报错,服务器不崩。

  • 高频事件(PlayerMoveEvent)慎用,开销大。

  • Simple names preferred; packages searched in order.

  • Common events listed above.

  • Third-party events need fully-qualified names.

  • Name clashes: disambiguate with fully-qualified names.

  • Unknown types error at start; server does not crash.

  • High-frequency events (PlayerMoveEvent) are expensive — use with care.


下一步 / Next Steps

下一章 [EventWrapper / EventWrapper] 讲怎么从事件对象里读取信息,例如谁触发的、破坏了什么方块。

Next, [EventWrapper / EventWrapper] shows reading data out of an event object — who triggered it, which block broke.