跳到主要内容

开发者 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} = 那位玩家)。可用的变量见 变量与占位符,动作写法见 脚本语法。