开发者 API
CloudDungeon 提供一组 Bukkit 事件,其他插件可以监听副本的开始、怪物组、通关、失败与玩家离开。
- 所有事件都在主线程触发。
- 你的监听器出错不会影响副本运行(会在控制台留一行警告)。
- 事件类都在
dev.cloudplugins.dungeon.api.DungeonEvent里。
引入
把 CloudDungeon.jar 当成编译期依赖(不要打包进你的插件):
// build.gradle
dependencies {
compileOnly files('libs/CloudDungeon-2.2.0.jar')
}
# 你的 plugin.yml
softdepend: [CloudDungeon]
事件一览
| 事件 | 什么时候 | 可以取消 |
|---|---|---|
DungeonEvent.PreStart | 出发前检查全部通过、扣入场券之前 | 可以 |
DungeonEvent.Start | 开场倒数结束、副 本正式开始 | |
DungeonEvent.MonsterGroup | 怪物组开始出怪 / 打完 | |
DungeonEvent.Clear | 通关 | |
DungeonEvent.Fail | 失败(时间到、团灭、脚本判定失败、所有人离开……) | |
DungeonEvent.Leave | 玩家离开副本(含副本结束时被送回) |
没有「阶段」(Stage)事件;要知道副本进行到哪里,监听 MonsterGroup,或从脚本调用你的插件(见 下方)。
所有事件都有
| 方法 | 说明 |
|---|---|
String getDungeonId() | 副本 ID(文件夹名称) |
String getDungeonName() | 副本显示名称(含颜色代码) |
Start、MonsterGroup、Clear、Fail、Leave 另外有
| 方法 | 说明 |
|---|---|
int getInstanceId() | 这一场的编号(/cd admin instance list 看到的 #) |
String getModeId() | 难度模式 ID;没有模式时是空字符串 |
List<UUID> getPlayerIds() | 这一场的所有队员(含掉线中的) |
List<Player> getPlayers() | 目前在副本里的在线玩家 |
PreStart(可取消)
| 方法 | 说明 |
|---|---|
List<Player> getPlayers() | 要出发的玩家 |
Player getLeader() | 队长 |
setCancelled(boolean) / isCancelled() | 取消这次出发;取消时不会扣任何东西 |
setCancelReason(String) / getCancelReason() | 取消时显示给玩家的原因(可用 & 色码),不写则显示默认提示 |
管理员的 /cd admin test 也会触发 PreStart。跨服时只在副本服务器触发。
MonsterGroup
| 方法 | 说明 |
|---|---|
String getGroup() | 怪物组 ID(monster.yml 里的名称) |
boolean isStarted() | true = 开始出怪,false = 打完 |
Clear
| 方法 | 说明 |
|---|---|
long getClearMillis() | 通关用时(毫秒,不 含全队掉线暂停的时间) |
String getRank() | 评价(S / A / B / C 或你自己设置的评价名称) |
Fail
| 方法 | 说明 |
|---|---|
String getReason() | 失败原因(已经套好颜色的文字) |
Leave
| 方法 | 说明 |
|---|---|
Player getPlayer() | 离开的玩家 |
String getReason() | 离开原因文字 |
Leave 在玩家离开副本时触发:/leave、被管理员踢出、被脚本 leave / kick、被其他插件传送出副本世界、在结算菜单按「立即返回」、grace: 0 时掉线,
以及副本正常结束、大家被一起送回去的时候(原因是「副本结束」)。离开的那一刻不在线的玩家(例如掉线超时)不会触发 Leave。
要知道副本是通关还是失败,请监听 Clear / Fail。
不要用 getDungeon() / getInstance()
事件上的 getDungeon()、getInstance() 返回的是插件内部对象(发布版的类型名称经过混淆),不属于公开 API,请不要调用。
需要副本 ID、场次、队员时,用上面的 getDungeonId()、getInstanceId()、getPlayerIds() 这些方法。
示例
import dev.cloudplugins.dungeon.api.DungeonEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.UUID;
public final class DungeonHook implements Listener {
/** 公会战期间不准开副本 */
@EventHandler
public void onPreStart(DungeonEvent.PreStart e) {
if (GuildWar.running()) {
e.setCancelled(true);
e.setCancelReason("&c公会战进行中,副本暂时关闭。");
}
}
@EventHandler
public void onGroup(DungeonEvent.MonsterGroup e) {
if (!e.isStarted() && e.getGroup().equals("boss")) {
// Boss 组打完
}
}
@EventHandler
public void onClear(DungeonEvent.Clear e) {
long seconds = e.getClearMillis() / 1000;
String rank = e.getRank();
String dungeon = e.getDungeonId();
for (UUID id : e.getPlayerIds()) {
// 记录每位队员的通关(含掉线中的人)
}
}
@EventHandler
public void onLeave(DungeonEvent.Leave e) {
Player p = e.getPlayer();
// 中途离开的处理
}
}
从脚本调用你的插件
很多时候更简单的做法是在副本脚本里直接执行你的插件指令,副本、玩家、时间等信息都能用变量带过去:
# end.yml
clear:
- "command myplugin dungeonclear {player} {dungeon_id} {elapsed_seconds} {rank}"
简写的 command 由控制台对副本里每位玩家各执行一次({player} = 那位玩家)。可用的变量见 变量与占位符,动作写法见 脚本语法。