事件
Cultivation 在 plugin.siren.API 下的 54 个 *Events 类中,暴露了 391 个事件:159 个可取消的 Pre* 前置事件,在变更发生之前触发;232 个后置事件,在变更落定之后触发。模组中几乎每一项机制都被暴露了两次:一次在变更之前,监听器可以否决它,或重新调整它的数值;一次在变更之后。v0.11.1 本版新增三个类:DaoDomainEvents(8 个事件,其中四个属于首领道域与共鸣)、SectArrayEvents(3 个)与 VeinTapEvents(7 个)。道印没有任何事件类;扩展转而能观察什么,见道域一节下的说明。v0.11.2 没有新增类,但新增了三个事件:CultivationEvents 上服务于死亡惩罚的 PreDeathPenaltyEvent 与 DeathPenaltyAppliedEvent,以及 SectEvents 上、在宗门大殿灵脉化为龙脉时触发的 SectVeinAscendedEvent。
每个类都遵循 CultivationEvents 上所记载的约定,因此学会一个便学会了全部 54 个。下面的表格由 plugin.siren.API 中的 Java 源码生成:每个事件、它能否取消,以及它身上的每一个 getter 与 setter,都是从代码里读出来的,所以数目不会与 jar 脱节。
PreXpGainEvent、XpGainEvent、PreLevelUpEvent 与 LevelUpEvent 同时存在于 BodyTemperingEvents 与 FistEvents 之中。务必用类名加以限定 —— 写 FistEvents.onXpGain(...),而不要裸引一个 XpGainEvent。
前置与后置
Pre* 事件继承自 plugin.siren.API.CancellableEvent,并在任何东西被施加之前触发。它给你两项能力:
event.setCancelled(true)否决该操作。派发一返回,模组即刻检查这个标志并放弃操作,不留下任何状态变更。之所以什么都不必回滚,是因为什么都还没被施加 —— 这正是这些事件先于事实触发的全部理由。一个被取消的前置事件,意味着与之配对的后置事件永不触发。- 事件上的 setter 用于重新调整驱动该操作的数字 —— 一次突破的灵气消耗、一门功法的冷却、一道天劫落雷的伤害、一次收服的概率。派发结束时监听器留在那些字段里的东西,就是模组实际采用的东西。这是从扩展中重塑一项机制、而不必碰配置文件的受支持途径。
后置事件是一个普通的 Java record。它无法被取消,纯粹是一则通知;待它触发时,变更早已在组件上可见。
CancellableEvent 恰好暴露两个方法:
| 方法 | 返回 | 说明 |
|---|---|---|
isCancelled() | boolean | 是否已有某个监听器否决了此操作。 |
setCancelled(boolean cancelled) | 否决该操作;传 false 则撤销否决。 |
即便有人取消了,每一个监听器仍会运行。 靠后的监听器尽可调用 setCancelled(false) 把操作放行,因此插件加载顺序决定了分歧中谁胜出。若你只想旁观,请改为监听后置事件。
并非每个前置事件都有同名的后置孪生,也并非每个后置事件都有前置事件:其中不少纯粹是通知,没有什么可否决的(SeasonEvents、DepthsEvents、SecretRealmEvents 就是刻意只设后置)。下面每张表里,前置事件都紧挨着列在它所守护的后置事件之前,「可取消」一列则标明哪些行是 Pre* 事件。
注册与线程
每个事件在其所属类上都有一个配套的 on* 注册方法 —— 共 391 个,一事件一个 —— 接受该事件类型的一个 Consumer:
CultivationEvents.onPreQiGain(event -> event.setAmount(event.amount() * 1.25F));
DaoEvents.onPathChange(event -> myPlugin.announce(event.player(), event.newPath()));
注册就是一次普通的 CopyOnWriteArrayList.add,可安全地从任何插件的 setup() 中、以任何加载顺序调用。没有反注册 —— 监听器的生命周期就是服务器的生命周期。
监听器是在事件所发生玩家的世界线程上同步调用的。在监听器内部经由惯常的访问器读取组件是安全的,但请勿阻塞;在触碰任何位于另一世界的东西之前,请自行切换线程(例如 CompletableFuture.runAsync(task, otherWorld))。抛出异常的监听器会被记录并跳过,因此一个写坏的扩展,既弄不垮模组自己的系统,也弄不垮监听同一事件的其他扩展。
许多类以 java.util.UUID 而非 PlayerRef 标识玩家,因为这些操作经常触及离线玩家 —— 一个被逐的门人、一场比会话活得更久的斗法、一位挂单在他离线时售出的卖家。BountyEvents、DaoDomainEvents、DaoDuelEvents、DepthsEvents、DuelEvents、LegacyEvents、MarketEvents、OathEvents、PagodaEvents、PartyEvents、RivalEvents、RogueEvents、SectArrayEvents、SectEvents、SoulEscapeEvents、StoreBenefitEvents、TeaEvents、TreasureEvents、VeinTapEvents、WagerEvents 与 WeiqiEvents 通篇如此;DwellingEvents、FormationEvents、PartnerEvents 与 SermonEvents 则把 UUID 标识符与 PlayerRef 玩家混着用。用 Universe.get().getPlayer(uuid) 解析 UUID,并检查 isValid()。
少数几个类带有额外约束,都在各自的 javadoc 里有所声明:
| 类 | 触发于 | 此时持有 | 该怎么做 |
|---|---|---|---|
SectEvents | 相关玩家的世界线程。 | SectManager 的锁。 | 读走你要的东西、交接出去、然后返回。切勿调用 SectManager 的变更方法。 |
MarketEvents | 相关玩家的世界线程。 | AuctionManager 的锁。 | 同理:切勿回调 AuctionManager 的变更方法。 |
BountyEvents | 引发该事件之物所在的世界线程。 | BountyManager 的监视器。 | 不要阻塞,不要重入 BountyManager,也绝不要去碰扩展自己的监视器 —— 锁序是 SeasonManager,然后你的扩展,然后 BountyManager。 |
SeasonEvents | 最先走到赛季泵的那条世界线程 —— 全服范围,而非某一位玩家的世界。 | SeasonManager 的监视器。 | 不要阻塞;碰组件之前先按玩家切换线程。启动时的赛季更替到不了任何扩展监听器,所以请改问 getCurrentSeasonId()。 |
WagerEvents | 对前置事件与 WagerPlacedEvent,是下注玩家的指令线程;对两个盘口结算事件,是锦标赛泵。 | 在 WagerMarketResolvedEvent 与 WagerMarketVoidedEvent 上,持有 DaoDuelTournamentManager 的监视器。 | 这两个事件上不加锁、不跨管理器调用;把需要的东西抄进你自己的队列。 |
DaoDomainEvents v0.11.1 | 施放者的世界线程,来自展开交互或道域自己的 tick。 | 无。 | 保持轻量,绝不在监听器里写入 Store。DomainClashEvent 在道域脉冲之内触发,就在它所引发的崩塌之前。 |
VeinTapEvents v0.11.1 | 布阵或劫掠玩家的世界线程,或某条指令线程(释放)。 | 不持有 VeinTapManager 的任何锁 —— 每个事件都在它的监视器之外触发。 | 保持轻量,不要在监听器里写入 Store。前置事件在所有关卡都通过之后才询问,所以否决不会留下任何已消耗的东西。 |
SectArrayEvents v0.11.1 | 升起事件在升起者的指令线程;SectArrayEndedEvent 则在最先察觉到结束的那条线程 —— 某个世界每秒一次的守阵机制,或撤下大阵的那条指令。 | 不持有 SectArrayManager 的任何东西 —— 三个事件都在它的监视器之外触发。 | 从活的 Sect 上读走你要的东西、交接出去、然后返回。切勿回调大阵的升起或撤下。 |
StoreBenefitEvents | 远程检查线程 —— 不是世界线程。 | 无。 | 找到玩家,检查 isValid(),碰任何组件之前先切到他的世界线程。 |
ProfileEvents | 所属的世界线程,处于任何 tick 系统之外。 | 无。 | 少有的例外:此处经由 Store 直接写入组件是安全的。 |
BodyTemperingEvents、FistEvents | 伤害管线之内,位于拥有受击实体的那条世界线程。 | 无。 | 保持轻量;绝不写入 Store。 |
LifespanEvents | LifespanSystem 的 tick,或某个指令处理器。 | 无。 | 经由访问器读取;写入则排到 CommandBuffer 上。 |
WagerEvents 的 javadoc 还记载:DuelEvents.DuelEndEvent、DaoDuelEvents.DaoDuelEndEvent 以及 CelestialEvents 那一对,是从同步的管理器方法内部触发的,因此同样的规矩也适用于这些事件上的监听器。
如何找到某个事件
54 个类,分成 8 组:
- 进阶、阶梯与存档 —— 8 个类,86 个事件。境界天梯本身、与之并列的两条肉身阶梯、伤患、第二条命,以及玩家保留的存档。
- 大道、功法与誓言 —— 6 个类,60 个事件。元素、阴阳与业力,天道与个人之道,道域,功法,战斗深度与天道誓言。
- 物品与炼制 —— 5 个类,31 个事件。掉落、丹药、灵核与秘籍,以及造出新物的诸般手艺:炼器、炼丹、锻造与符箓,外加兵器之中的灵。
- 灵兽 —— 2 个类,24 个事件。伙伴,以及繁育出新伙伴的过程。
- 宗门、坊市与同道 —— 10 个类,88 个事件。宗门与宗门之间的战事,被围宗门的战时大阵,侍奉大殿的人,功德,队伍与道侣,拍卖行与悬赏令。
- 斗法与较量 —— 5 个类,26 个事件。两位玩家出于自愿而彼此对抗、或并肩进行的一切。
- 世界 —— 14 个类,63 个事件。阵法与洞府,灵脉上的引脉阵,天穹,全服范围的遭遇,你前往的去处,以及你在那里的所获。
- 任务、赛季与宝阁 —— 4 个类,13 个事件。剧情,共享的赛季时钟,以及从网络商店送达的购买。
每个类的标题都有一个形如 #<name>-events 的固定锚点,见上表第一列。
进阶、阶梯与存档
境界天梯本身、与之并列的两条肉身阶梯、伤患、第二条命,以及玩家保留的存档。
修炼核心
plugin.siren.API.CultivationEvents —— 48 个事件(22 个可取消),涵盖灵气、打坐、仪式、突破、晋阶、跌境、v0.11.2 死亡惩罚、天劫、心魔劫、走火入魔、幻境劫、心魔宿敌之战、洗髓之礼、飞升、轮回、种族、本命法宝、天赋树与玩家击杀。面向玩家的文档:境界与阶段、聚灵采气、天劫、种族、本命法宝、天赋树、飞升、轮回、走火入魔、幻境劫、心魔宿敌之战、死亡惩罚。
v0.11.2 两个死亡惩罚事件由濒死玩家的死亡回调触发,位于其世界线程上,此时该次死亡的 CommandBuffer 仍然开着。读取你需要的内容;若必须修改这位修士,请通过那个缓冲区进行,而不要直接写入 Store。PreDeathPenaltyEvent 是唯一的否决点:取消它既免去这次损失,也不会把这次死亡记作一次受罚;而 setPercent(0) 虽然什么都不取走,这次死亡仍计入阶梯的下一档(DeathPenaltyAppliedEvent 也仍会触发,其 qiLost() 为 0)。
此类中声明的枚举:
RitualType:BREAKTHROUGH—— 巅峰阶段 → 下一重境界;ADVANCEMENT—— 当前境界之内的一次子阶段晋阶;REFINEMENT—— 炼器:淬炼手中所持的兵器,而非修士本人。MeditationStopReason:COMMAND—— 他们用 /cultivation meditate 自行关掉了它;MOVEMENT—— 他们离开了落座之处;RITUAL_COMPLETE—— 一次境界突破或子阶段晋阶完成,修士从挣得它的座位上起身。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreQiGainEvent | 是 | 灵气即将入账,对每一处来源皆然 —— 打坐周期、赌斗结算、管理授予 —— 且在模组自身所有倍率之后。 | ref()、player()、amount() / setAmount(float)、baseAmount()(任何监听器动手之前的值)。 |
QiGainEvent | 否 | 灵气已入账。 | ref()、player()、amount()、totalQi()。 |
PreMeditationStartEvent | 是 | 玩家即将盘坐打坐。取消则让他继续站着。 | ref()、player()。 |
MeditationStartEvent | 否 | 玩家已盘坐打坐。 | ref()、player()。 |
PreMeditationStopEvent | 是 | 玩家即将停止打坐。取消可让一场仪式不可打断,或压制移动中断。 | ref()、player()、reason()。 |
MeditationStopEvent | 否 | 玩家已停止。任何仪式惩罚都已施加。 | ref()、player()、reason()。 |
PreRitualStartEvent | 是 | 一场计时仪式即将开始。取消后玩家继续打坐(照常存灵气),却永不进入仪式。 | ref()、player()、type()、requiredSeconds() / setRequiredSeconds(float)。 |
RitualStartEvent | 否 | 首次累积仪式进度的那一 tick。 | ref()、player()、type()。 |
PreBreakthroughEvent | 是 | 一次境界突破即将完成。取消可把他按在巅峰阶段 —— 进度重置,他可以再试。 | ref()、player()、fromRealm()、toRealm()、qiCost() / setQiCost(float)。 |
BreakthroughEvent | 否 | 突破已完成;其阶段为 EARLY。 | ref()、player()、newRealm()。 |
PreAdvancementEvent | 是 | 一次子阶段晋阶即将完成。取消可把他按在原处。 | ref()、player()、realm()、fromStage()、toStage()、qiCost() / setQiCost(float)。 |
AdvancementEvent | 否 | 晋阶已完成。 | ref()、player()、realm()、newStage()。 |
PreDemotionEvent | 是 | 玩家即将因放弃仪式而折损一个子阶段。取消则他全身而退 —— 存蓄的灵气也保住了。 | ref()、player()、realm()、oldStage()、newStage()、wasBreakthrough()。 |
DemotionEvent | 否 | 跌境已落定;存蓄灵气被清空,随之授予的天赋点被收回。 | ref()、player()、realm()、oldStage()、newStage()、wasBreakthrough()。 |
PreDeathPenaltyEvent v0.11.2 | 是 | 一次死亡即将按死亡惩罚折损修士的灵气。取消则免去这次死亡的惩罚 —— 这一击也不会被记录,因此不会计入下一次死亡的档位。调用 setPercent 则改为扣除当前小阶灵气的另一个比例。它只会在这次死亡尚未被豁免(渡劫、斗法、副本、绕过等)时被询问,且在单个击杀者上限之后,因此本就免罚的死亡永远不会到达监听器。 | ref()、player()、strike()(这是滚动窗口中的第几次死亡,1 为第一次,含本次)、percent() / setPercent(float)(即将取走的当前小阶灵气的百分比;100 为一整阶)、basePercent()(任何监听器改动之前的值)。 |
DeathPenaltyAppliedEvent v0.11.2 | 否 | 惩罚已落定。灵气已被取走,若 stageLost() 为 true,则小阶也已跌落(经由常规的跌境,所以 PreDemotionEvent 与 DemotionEvent 会先触发)。被取消的 PreDeathPenaltyEvent 永远不会产生此事件。 | ref()、player()、strike()、strikesInWindow()(仍有效的受罚次数,含本次)、percent()(经前置事件监听器改动之后)、qiLost()(从灵气池中取走的量,早于跨阶跌落时的余量结转)、stageLost()、oldRealm()(跌阶绝不会改变境界)、oldStage()、newStage()、newQi()。 |
PreTribulationStrikeEvent | 是 | 天劫雷霆即将劈向仪式中的修士。取消可完全放过他 —— 无雷、无声、无伤。把伤害设为 0 则让雷落得无伤无害。 | ref()、player()、damage() / setDamage(float)(在致死上限之后、护甲之前)、breakthroughRitual()。 |
TribulationStrikeEvent | 否 | 雷已落下。 | ref()、player()、damage()、breakthroughRitual()。 |
PreHeartDevilTrialEvent | 是 | 一次心魔侵扰即将折磨仪式中的修士。把扣减设为 0 可让那幻象纯粹成为装饰。 | ref()、player()、composureDrain() / setComposureDrain(float)、leanFraction()(0–1)、pulseIndex()(自 0 起)、breakthroughRitual()。 |
HeartDevilTrialEvent | 否 | 一次侵扰已结算。 | ref()、player()、composureRemaining()、deviated()、breakthroughRitual()。 |
PreQiDeviationEvent | 是 | 道心已碎,走火入魔即将施加。取消可免去这份惩罚 —— 仪式仍然结束。 | ref()、player()、demotes() / setDemotes(boolean)、qiLoss() / setQiLoss(float)、breakthroughRitual()。 |
QiDeviationEvent | 否 | 惩罚已落定。demoted() 与 qiLost() 中恰有一个承载它。 | ref()、player()、demoted()、qiLost()、breakthroughRitual()。 |
PreRaceChangeEvent | 是 | 种族即将改变。取消后种族菜单只会报告「未发生变更」。 | ref()、player()、oldRace()、newRace()、adminOverride()。 |
RaceChangeEvent | 否 | 种族已改变。管理员把种族设为玩家已有的那一个时不触发。 | ref()、player()、oldRace()、newRace()、adminOverride()。 |
PreSkillUnlockEvent | 是 | 一个天赋树节点即将解锁。取消则他的点数不会被花掉。 | ref()、player()、node()、pointCost() / setPointCost(int)。 |
SkillUnlockEvent | 否 | 节点已解锁;点数已花,各项修正已重新施加。 | ref()、player()、node()。 |
PreRespecEvent | 是 | 一次天赋树洗点即将执行。 | ref()、player()、refundedPoints() / setRefundedPoints(int)。 |
RespecEvent | 否 | 每个节点都已清空,点数已返还。 | ref()、player()、refundedPoints()。 |
PreLifeBoundLevelUpEvent | 是 | 一件本命法宝即将升级。取消可把它按在当前等级 —— 经验仍会存下。 | owner()、item()(写入升级之前的那一叠)、oldLevel()、newLevel()。 |
LifeBoundLevelUpEvent | 否 | 法宝已升级。 | owner()、item()(已更新)、newLevel()。 |
PreAscensionEvent v0.8.0 | 是 | 一位修士即将开始飞升渡劫。取消则让他未经一试地留在巅峰 —— 这是服务器把天梯的结局挂在自家某样东西(一条任务、一件物品、一个日期)之后所需的唯一钩子。 | ref()、player()、prestiged()(他是否打算重修再起,而非留驻巅峰)。 |
AscensionEvent v0.8.0 | 否 | 一次飞升已被熬过。若结局是重修,则此事件触发时已经重置回第一重境界。它刻意不是带着特殊境界的 BreakthroughEvent —— 飞升不是突破,把它当作突破的监听者会记错东西。 | ref()、player()、ascensionCount()、prestiged()。 |
AscensionFailedEvent v0.8.0 | 否 | 一次尝试以失败告终。 | ref()、player()、abandoned()(中途离场,而非身死)。 |
PreTribulationOmenEvent | 是 | 一场仪式的风暴征兆判定即将裁定,就在仪式的首个 tick 上。取消可强制无征兆,不论天空掷出了什么(无消息、不锁定;选择加入的请求仍保持待命);setStorm 则可朝任一方向强行定下结果。 | ref()、player()、naturalStormDetected()、storm() / setStorm(boolean)、breakthroughRitual()。 |
TribulationOmenEvent | 否 | 一场仪式的风暴征兆已在首个 tick 上裁定。storm 表示它是否锁定:为 true 则仅在这一次仪式尝试的余下时段里,启用更凶险、回报更丰厚的版本。仅当判定确实发生时才触发(玩家已选择加入,或 Tribulation-Storm-Omen-Opt-In-Required 为 false)。 | ref()、player()、storm()、breakthroughRitual()。 |
PreDreamTrialEvent | 是 | 一次幻境劫的侵扰即将考验空镜之中的修士。取消可整次跳过;调整 setComposureDrain 可改变它咬得多狠(设为 0 则让那倒影纯属装饰)。 | ref()、player()、composureDrain() / setComposureDrain(float)、pressure()、pulseIndex()。 |
DreamTrialEvent | 否 | 幻境劫的空镜在一次尝试途中考验了一名修士。composureRemaining 是本次侵扰扣减之后剩下的道心(碎裂时为 0),broken 仅在击碎道心、令此次尝试失败的那一次侵扰上为 true,pressure 则是缩放扣减量的 0–1 比例。 | ref()、player()、composureRemaining()、broken()、pressure()。 |
PreInnerDemonTrialEvent | 是 | 一次心魔宿敌之战的侵扰即将冲击决战中的修士。取消可整次跳过;调整 setComposureDrain 可改变它咬得多狠(设为 0 则让那幻象纯属装饰)。 | ref()、player()、composureDrain() / setComposureDrain(float)、echoIntensity()、pulseIndex()、nemesisEcho()。 |
InnerDemonTrialEvent | 否 | 一场心魔宿敌之战冲击了决战中的修士。composureRemaining 与 broken 的含义同幻境劫;echoIntensity 是缩放扣减量的 0–1 比例,nemesisEcho 则在幻影顶着一位当前宿敌的面孔时为 true。 | ref()、player()、composureRemaining()、broken()、echoIntensity()、nemesisEcho()。 |
PreCleanseRiteEvent | 是 | 洗髓之礼的一轮即将检验仪式中的修士。取消可整轮跳过;调整 setComposureDrain 可改变它咬得多狠(设为 0 则让这一轮纯属装饰)。 | ref()、player()、composureDrain() / setComposureDrain(float)、targetMagnitude()、pulseIndex()、companionPresent()。 |
CleanseRiteEvent | 否 | 洗髓之礼的一轮检验了仪式中的修士。broken 仅在致使洗髓失败的那一轮上为 true(所针对的损伤随之加深),targetMagnitude 是所针对损伤入礼时的强度,companionPresent 则在结缘的道侣、师父或弟子近到足以减轻扣减时为 true。 | ref()、player()、composureRemaining()、broken()、targetMagnitude()、companionPresent()。 |
PreRitualAbortEvent | 是 | 修士请求从已启动的突破或晋阶中退出。/cultivation meditate abort 报价时触发一次,abort confirm 时再触发一次,因此否决会赶在玩家被告知代价之前就回绝;于是同一次退出可能触发两次。取消即回绝;此时尚未扣任何东西。取消后指令自己不发任何消息,所以监听器应当自行说明缘由。 | ref()、player()、type()、qiLost()。 |
RitualAbortEvent | 否 | 修士以 /cultivation meditate abort 从已启动的突破或晋阶中退出。qiLost 是散去的存蓄灵气(已扣除);不会跌境。他们是经一次普通的 COMMAND 停止而起身的,所以 MeditationStopEvent 也会触发。 | ref()、player()、type()、qiLost()。 |
AscensionLegacyEvent | 否 | 一次飞升以传承结局告终(/ascend legacy sect 或 /ascend legacy self)。总是在同一次飞升的 AscensionEvent 之后紧接着触发,因为传承结局本身也是一种重修式的重置。sectBeneficiary 表示实际授予了谁:为宗门铭刻传承碑则为 true,授予传承之尘则为 false —— 包括那种本欲惠及宗门、却因宗门已不在而退为传承之尘的尝试,由 sectFallback 加以区分。仅当 sectBeneficiary 为 true 时才设置 sectName。 | ref()、player()、sectBeneficiary()、sectFallback()、sectName()。 |
PreReincarnationEvent | 是 | 一位修士即将开始轮回。取消则让他未经一试地留在当前境界 —— 这是服务器把这一结局挂在自家某样东西(一条任务、一件物品、一个日期)之后所需的唯一钩子,与 PreAscensionEvent 对另一个终章所起的作用相同。 | ref()、player()。 |
ReincarnationEvent | 否 | 一位修士完成了轮回(转世)—— 与飞升并列的另一个终章。fromRealm / toRealm 分别是舍下的境界,与部分重置之后落脚的境界;bloodlinePointsGranted 是刚刚加入其 ReincarnationLedger 条目的血脉点数(是累计增量,不是新的总数)。 | ref()、player()、fromRealm()、toRealm()、bloodlinePointsGranted()。 |
ReincarnationFailedEvent | 否 | 一位修士的轮回尝试以失败告终。 | ref()、player()、abandoned()。 |
PlayerKillEvent | 否 | 一位修士击杀了另一位,且这次击杀有报酬。通用的玩家对玩家钩子:模组自己为一次击杀支付的一切(魔道灵气、大道行止、五行奖励、掉落的秘籍)都在它触发之后立即记账。仅对通过防刷关卡(Pk-Same-Victim-Cooldown-Seconds、Pk-Min-Victim-Realm)的击杀触发,对自杀、环境致死,以及正在遁走的元婴所落下的击杀则永不触发。刻意不设 Pre 孪生事件。sanctionedDuel 在这场死亡了结了一场斗法时为 true;模组此时会扣下自己的 PvP 奖励,替击杀付酬的扩展也该如此。 | killer()、killerPlayer()、victim()、victimPlayer()、sanctionedDuel()。 |
声明为 @Nullable 的有:player()(所有携带它的事件);sectName();victimPlayer()。
这些所覆写的配置键:setRequiredSeconds 对应 Breakthrough-Base-Seconds 与 Advancement-Base-Seconds;PreTribulationStrikeEvent.setDamage 对应 Tribulation-Damage-Percent-Of-Max-Health 与 Advancement-Tribulation-Damage-Percent-Of-Max-Health;setComposureDrain 对应 HeartDevil-Composure-Drain-Per-Pulse;setDemotes / setQiLoss 对应 HeartDevil-Deviation-Demotes 与 HeartDevil-Deviation-Qi-Loss-Percent;PreRespecEvent 映照 Respec-Enabled 与 /cultivation respec 指令。见配置与指令。
淬体
plugin.siren.API.BodyTemperingEvents v0.7.1 —— 6 个事件(3 个可取消),涵盖第二条进阶阶梯:不靠采气、只靠挨打攀登的那一条 —— 伤害所换来的经验、经验所换来的层数,以及这些层数所归并成的九个淬体阶段(锻体境)。面向玩家的文档:淬体。
这里的每个监听器都运行在伤害管线之内,位于拥有受击实体的那条世界线程上:经由给你的访问器读取,绝不从中写入 Store,并保持轻量。PreXpGainEvent 可以缩放或拒绝一击的价值,扩展正是借此添加倍率,而不必重新实现护甲扫描;PreLevelUpEvent 则让躯体停在当前层数,同时经验照旧存着。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreXpGainEvent | 是 | 修士即将因落在身上的伤害获得淬体经验。数额可改,而不只是可拒 —— 这是为单个玩家或单个场景重新调整整条阶梯的受支持做法。 | ref()、player()、amount() / setAmount(float)、level()。 |
XpGainEvent | 否 | 经验已入账。 | ref()、player()、amount()、level()。 |
PreLevelUpEvent | 是 | 即将提升一级淬体。取消则维持原位。 | ref()、player()、fromLevel()、toLevel()。 |
LevelUpEvent | 否 | 已提升。一击跨越多级时逐级触发。 | ref()、player()、fromLevel()、toLevel()。 |
PreStageBreakthroughEvent | 是 | 一次淬体阶段突破即将庆贺。与 PreLevelUpEvent 不同,取消并不会把躯体按在旧阶段上 —— 阶段由层数推出,而层数早已入账。它压制的是那番庆典:标题、音效、粒子与全服广播。 | ref()、player()、fromStage()、toStage()。 |
StageBreakthroughEvent | 否 | 一副躯体跨入了新的淬体阶段(锻体境)—— 由层数推出的九级里程碑。每次经验入账至多触发一次,哪怕一击跨越了好几层。 | ref()、player()、fromStage()、toStage()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
整套系统的总开关:Body-Tempering-Enabled。注意经验是按护甲之后计算的,因此监听器读到的 amount() 是真正穿透过来的那一部分,而非挥出的那一下。
拳法
plugin.siren.API.FistEvents v0.7.4 —— 4 个事件(2 个可取消),涵盖第三条阶梯,靠空手击中敌人攀登 —— 它是淬体的镜像,后者的收入是承受的伤害。经验按真正穿透的伤害计算,所以一记被护盾整个吃掉的拳头什么也教不会你。面向玩家的文档:拳法。
修士空手打出的每一记击打都会触发这些事件,且从伤害管线内部触发:保持监听器轻量,绝不从中写入 Store。PreXpGainEvent 携带一个可变的数额,把它设为 0 或更小,则直接取消这次入账。这四个事件的名字与 BodyTemperingEvents 的相同 —— 请用类名加以限定。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreXpGainEvent | 是 | 即将为一记空手之击入账经验。与淬体的对应事件一样,它不止可取消 —— 它携带可变的数额,监听器因而可以缩放奖励,而不只是放行或禁止。把数额设为 0 或更小,则直接取消这次入账。 | ref()、player()、level()、amount() / setAmount(float)。 |
XpGainEvent | 否 | 经验已入账。amount 是实际授予的量,已计入前置事件的缩放。 | ref()、player()、level()、amount()。 |
PreLevelUpEvent | 是 | 即将升一级。取消则让修士留在原处;经验仍会存下。 | ref()、player()、fromLevel()、toLevel()。 |
LevelUpEvent | 否 | 修士的拳法升了一级。一击跨越多级时逐级触发。 | ref()、player()、fromLevel()、toLevel()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
寿元
plugin.siren.API.LifespanEvents v0.10.2 —— 6 个事件(2 个可取消),涵盖寿元:每份存档按其所达最高境界定下的在线游玩小时预算 —— 延寿、凋零、复原与到期。该系统本身在服务器上默认关闭;CultivationAPI.isLifespanEnabled() 可查知它是否开启。面向玩家的文档:寿元。
每个监听器都运行于 LifespanSystem 的 tick,或拥有该实体的世界线程上的某个指令处理器之中。经由给你的访问器读取,并把写入排到 CommandBuffer 上。
此类中声明的枚举:
ExtendSource:BREAKTHROUGH—— 境界最高纪录的上升,纯属告知性质(它为何跳过前置事件,见LifespanManager自己的文档);PILL—— 延寿丹;ADMIN——/cultivation admin extendlifespan。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreLifespanExtendEvent | 是 | 即将授予额外小时(仅限 ExtendSource.PILL / ExtendSource.ADMIN —— ExtendSource.BREAKTHROUGH 的境界纪录上升,在寿元察觉时早已发生,故只触发后置事件)。取消可直接拒绝这次授予,或缩放 setHours 以改变实际存入的量。 | ref()、player()、source()、hours() / setHours(float)。 |
LifespanExtendEvent | 否 | 额外小时已实际存入(对 ExtendSource.BREAKTHROUGH 而言,则是境界纪录所定的预算上升了)。hours 是实际施加的量,已计入 PreLifespanExtendEvent 的缩放。 | ref()、player()、hours()、source()。 |
LifespanWitherEvent | 否 | 一位修士的寿元预算归零,进入凋零的宽限状态。 | ref()、player()。 |
LifespanRestoreEvent | 否 | 一位修士的寿元时钟被重置为一份新的预算 —— 一次真正的轮回、一次真正的飞升、LifespanConfig.ExpiryAction.NOTHING 化解凋零,或寿终自己的重置(后者另会触发 LifespanExpireEvent)。 | ref()、player()。 |
PreLifespanExpireEvent | 是 | 一位修士的寿元预算即将归零并进入凋零。在此取消,则对本次越线彻底否决凋零 —— 时钟停在 0,下个 tick 又会触发,所以意图给予缓刑的扩展还应同时延长预算(否则立刻又会被问一遍)。 | ref()、player()。 |
LifespanExpireEvent | 否 | 一位修士的凋零宽限已耗尽,Lifespan-Expiry-Action 即将执行。此事件不可取消 —— 触发时宽限期已然过去;要否决凋零本身,请在更上游使用 PreLifespanExpireEvent。 | ref()、player()、action()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
经脉损伤
plugin.siren.API.MeridianEvents v0.9.1 —— 5 个事件(3 个可取消),涵盖一处命名的经脉损伤被施加或加深、被治愈,以及丹田龟裂的灵气外溢被启动。面向玩家的文档:经脉损伤。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreMeridianInjuryEvent | 是 | 一处损伤即将落下(若已背负则是加深)。取消可直接回绝;用 setMagnitude / setDurationSeconds 可在写入之前重新缩放这次掷出的结果。 | ref()、player()、injury()、cause()、magnitude() / setMagnitude(float)、durationSeconds() / setDurationSeconds(float)。 |
MeridianInjuryEvent | 否 | 一处损伤已落下(或已加深)—— 写入早已完成。 | ref()、player()、injury()、magnitude()、durationSeconds()。 |
PreMeridianCureEvent | 是 | 一处损伤即将治愈。取消可回绝(它仍然留着)。 | ref()、player()、injury()、cureSource()。 |
MeridianCureEvent | 否 | 一处损伤彻底消退(静候自愈、打坐调养,或一次明确的治疗)。 | ref()、player()、injury()、cureSource()。 |
PreMeridianSpillEvent | 是 | 丹田龟裂的灵气外溢即将启动(仅在落下/加深时触发一次,而非每个 tick)。取消则把此后的灵气增长封顶在新的上限,而不抽走已存的超额部分;用 setRatePerSecond 可调整超额部分流失的快慢。 | ref()、player()、excessQi()、ratePerSecond() / setRatePerSecond(float)。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
元婴遁走
plugin.siren.API.SoulEscapeEvents v0.10.2 —— 8 个事件(3 个可取消),涵盖致命一击下的缓刑(元婴遁走)、追杀,以及它如何收场:存活、湮灭、超时或放弃。面向玩家的文档:元婴遁走。
没有任何公开门面可以开启一场遁走;只有一记符合条件的致命一击才会开启。这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此处有两个枚举:SanctuaryKind(ABODE、SECT_HALL、FORMATION)与 ForfeitReason(DISCONNECT、RELOG_RESOLVED、WORLD_CHANGE、PLUGIN_RELOAD)。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreSoulEscapeBeginEvent | 是 | 致命一击即将被取消,元婴即将开始逃亡。取消则不遁走:不扣任何东西,那一击仍是致命的。三个 setter 可重新调整时限与各项代价。 | soul()、killer()、realm()、windowSeconds() / setWindowSeconds(float)、qiCostPercent() / setQiCostPercent(float)、lifespanHours() / setLifespanHours(float)。 |
SoulEscapeBeginEvent | 否 | 遁走开始:致命一击被取消,元婴正在逃亡。windowSeconds 是时限的长度;qiSpent 与 lifespanHoursSpent 是这次尝试所扣的代价。 | soul()、killer()、realm()、windowSeconds()、qiSpent()、lifespanHoursSpent()。 |
PreSoulSurviveEvent | 是 | 一个逃亡中的元婴刚刚进入一处庇护所。取消则这处庇护所不算数:元婴继续逃亡。setter 可调整恢复的生命、虚弱的时长,以及付给击杀者的功德。 | soul()、killer()、kind()、world()、chunkX()、chunkZ()、restoreHealthPercent() / setRestoreHealthPercent(float)、weakenedMinutes() / setWeakenedMinutes(float)、spareMerit() / setSpareMerit(float)。 |
SoulEscapeSurviveEvent | 否 | 逃亡的元婴抵达庇护所并回归肉身,虚弱 weakenedMinutes 分钟。kind 表明是哪一类庇护所;meritToKiller 是因饶恕他们而记在击杀者名下的功德。 | soul()、killer()、kind()、world()、chunkX()、chunkZ()、weakenedMinutes()、meritToKiller()。 |
PreSoulExtinguishEvent | 是 | 一击刚刚落在逃亡的元婴身上。取消则这一击不起作用;元婴继续逃亡。 | soul()、extinguisher()、hitsSoFar()、hitsRequired()、extraKarma() / setExtraKarma(float)、extraYinShift() / setExtraYinShift(float)。 |
SoulEscapeExtinguishEvent | 否 | 一个逃亡的元婴在抵达安全之处前再度被击中,遁走就此以真正的死亡告终。extraKarma 与 extraYinShift 是在寻常击杀自身的代价之上,另记在湮灭者名下的额外惩罚。 | soul()、extinguisher()、extraKarma()、extraYinShift()。 |
SoulEscapeTimeoutEvent | 否 | 时限已尽而元婴仍未抵达庇护所,遁走以真正的死亡告终。 | soul()、killer()。 |
SoulEscapeForfeitEvent | 否 | 遁走未能归结为存活、湮灭或超时便告终止。reason() 说明缘由:DISCONNECT、RELOG_RESOLVED、WORLD_CHANGE 或 PLUGIN_RELOAD。 | soul()、killer()、reason()。 |
声明为 @Nullable 的有:killer()(所有携带它的事件)。
修行传承
plugin.siren.API.LegacyEvents v0.10.1 —— 2 个事件(1 个可取消),涵盖一位隐退修士的突破消耗减免加成送达他所选定的传人。这份馈赠可取消,也可重新调整。面向玩家的文档:修行传承。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreLegacyPayoutEvent | 是 | 一份传承加成即将授予或排入队列。取消可直接回绝 —— 此时尚未写入或排队任何东西。监听器也可在派发结束前用 setReductionPercent / setExpiresAtMillis 重新缩放;留在这些字段里的值,就是实际授予或排队的值。 | benefactorUuid()、benefactorName()、heirUuid()、retiringRealmOrdinal()、sourceProfileName()、reductionPercent() / setReductionPercent(float)、expiresAtMillis() / setExpiresAtMillis(long)。 |
LegacyPayoutEvent | 否 | 一份传承加成已实际送达(或已排入)传人 —— 这里所述的减免是最终数额:即时发放时是计入近期存档缩减之后的值,排队发放时则是缩减之前的基础值(见 queued)。 | benefactorUuid()、benefactorName()、heirUuid()、reductionPercent()、expiresAtMillis()、sourceProfileName()、queued()。 |
修炼存档
plugin.siren.API.ProfileEvents v0.7.0 —— 7 个事件(3 个可取消),涵盖玩家的修炼存档:在已存的修士之间切换、创建一位、抹去一位,以及试炼存档到期。面向玩家的文档:修炼存档。
这些事件携带一个 Profile 负载(CultivationProfilesComponent.Profile)—— 常用的成员有 getName()、isTest()、getExpiresAtMillis() 与 remainingMillis(long)。注意到期没有前置事件:试炼存档的时限无法被否决。
这些监听器可以写入。 在整个接口中独此一处:存档监听器运行在所属世界线程上,且不处于任何 tick 系统之内,因此在此处经由 Store 直接读取并写入组件是安全的 —— 这是「监听器内绝不写入」这条通则唯一的例外。这是刻意为之:一个进阶体系扩展必须能在切换存档时保存并载入自己的状态(见 ProgressionProvider.supportsProfiles())。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreProfileSwitchEvent | 是 | 玩家即将切换存档。取消可回绝这次切换 —— 指令会报告切换被拦下。 | ref()、player()、from()(首次补建存档时为 null)、to()。 |
ProfileSwitchEvent | 否 | 切换已生效 —— 抵达存档所对应的境界、灵气、种族、大道、天赋树与功法皆已写入组件。请在此载入你自己的按存档状态。 | ref()、player()、from()(首次补建存档时为 null)、to()。 |
PreProfileCreateEvent | 是 | 一份全新存档即将创建。取消可回绝之 —— 不占用任何存档位。 | ref()、player()。 |
ProfileCreateEvent | 否 | 存档已存在,玩家已切换至其上。 | ref()、player()、profile()。 |
PreProfileDeleteEvent | 是 | 一份存档即将被永久删除。取消可保留它。 | ref()、player()、profile()。 |
ProfileDeleteEvent | 否 | 存档已被删除。请在此清除你自己为其保存的状态。 | ref()、player()、profile()。 |
ProfileExpireEvent | 否 | 一份试炼存档的墙上时限已到期。wasActive() 表明玩家此前是否正在游玩它 —— 若是,他此刻刚被放回了一份真正的存档上。 | ref()、player()、profile()、wasActive()。 |
声明为 @Nullable 的有:from()(所有携带它的事件)。
若你的扩展自行维系一套进阶体系,请处理 PreProfileSwitchEvent(保存即将离开的那份存档)与 ProfileSwitchEvent(载入抵达的那份),随后令 ProgressionProvider.supportsProfiles() 返回 true —— 在你这样做之前,只要你的进阶体系仍装着,切换就会被直接回绝,而非做到一半。上限同样可由扩展提升:接口参考上的 registerProfileCap 可将默认的三个存档位上调(上限为六,取最高的注册值,且上限下调时绝不会销毁任何东西)。
大道、功法与誓言
元素、阴阳与业力,天道与个人之道,道域,功法,战斗深度与天道誓言。
大道与业力
plugin.siren.API.DaoEvents —— 14 个事件(6 个可取消),涵盖元素、偏移、阴阳之衡、德行道途与业力。面向玩家的文档:灵根、天道与业力。
阴阳与业力几乎在每个打坐周期与每次击杀时都在变动,因此这些事件触发得很频繁。请让监听器保持轻量;若你只关心结果,请优先用道途与偏移事件。
此类中声明的枚举:
ElementChangeReason:CHOSEN—— 他们亲自择定的:免费的首次选择,或付费的改换;DRIFT—— 他们的行止压倒了所择之道,于是它自行转化。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreDaoElementChangeEvent | 是 | 修士即将择定或改换某一元素。取消后它会报告「道未变更」。 | ref()、player()、dao()、oldElement()(首次择道时为 null)、newElement() / setNewElement(DaoElement)、reason()、qiCost() / setQiCost(float)(首次择道与 DRIFT 时恒为 0)。 |
DaoElementChangeEvent | 否 | 元素已改变。 | ref()、player()、dao()、oldElement()、newElement()、reason()、qiCost()。 |
PreDaoAffinityGainEvent | 是 | 行止亲和即将被加到某一元素上 —— 那正是最终导致偏移的压力。 | player()、dao()、element()、amount() / setAmount(float)。 |
DaoAffinityGainEvent | 否 | 亲和已加上。 | player()、dao()、element()、amount()。 |
DaoDriftWarningEvent | 否 | 修士已被警示其道正在偏移。每出现一个新的威胁元素触发一次。 | player()、dao()、chosenElement()、driftingTo()。 |
PreAlignmentShiftEvent | 是 | 一次阴阳偏移即将施加。种族偏向的分流发生在此之后。 | dao()、amount() / setAmount(float)(原始偏移量)、towardYin()。 |
AlignmentShiftEvent | 否 | 阴阳之衡已移动。 | dao()、yin()、yang() —— 种族偏向分流之后实际加上的量。 |
PrePathChangeEvent | 是 | 德行道途即将改变。取消后底层的阴阳之衡分毫不动,因此这只是压制了那次重新归类。 | player()、dao()、oldPath()、newPath()。 |
PathChangeEvent | 否 | 道途已改变并已昭告。 | player()、dao()、oldPath()、newPath()。 |
PreKarmaGainEvent | 是 | 业力即将因一次击杀而记账。取消可让账簿保持清白。 | player()、dao()、amount() / setAmount(float)、farmedKill()(防刷窗口内的重复击杀 —— 不产灵气,业力却更重)。 |
KarmaGainEvent | 否 | 业力已记账。 | player()、dao()、amount()、total()(在 Karma-Max 封顶之后)、farmedKill()。 |
KarmaClearedEvent | 否 | 业力已消解 —— 或因挺过一道天劫落雷,或因久不杀生的墙上时钟衰减。 | dao()、amount()、total()、fromTribulation()。 |
PreDevilHarvestEvent | 是 | 一名魔道修士即将从被斩杀的玩家身上掠夺存蓄灵气。 | killer()、killerPlayer()、qi() / setQi(float)。 |
DevilHarvestEvent | 否 | 掠夺已发生。 | killer()、killerPlayer()、qi()。 |
声明为 @Nullable 的有:ref()(所有携带它的事件);player()(所有携带它的事件);oldElement()(所有携带它的事件)。
这些所覆写的配置键:PreDaoElementChangeEvent.setQiCost 对应 Dao-Switch-Base-Qi-Cost 与 Dao-Switch-Qi-Cost-Realm-Multiplier;PreDaoAffinityGainEvent.setAmount 对应 Dao-Affinity-Per-Elemental-Kill(由 Dao-Drift-Margin 决定偏移何时触发);PreAlignmentShiftEvent.setAmount 对应 Meditation-Alignment-Shift-Per-Tick 与 Kill-Yin-Amount,其后置事件的分流则由 Qi-Alignment-Yin-Bias-Percent 支配;PreKarmaGainEvent.setAmount 对应 Karma-Per-Player-Kill 与 Karma-Per-Farmed-Kill;PreDevilHarvestEvent.setQi 对应 Path-Devil-PK-Qi-Reward。
大道领悟
plugin.siren.API.DaoComprehensionEvents v0.9.0 —— 11 个事件(5 个可取消),涵盖叠在元素之道上的那一层:天道的领悟轨道、开放的个人之道注册表(内置七门 —— 剑道、杀戮道、时空道、灵兽道、魔道、炼体道与元素道 —— 外加模组在它们之侧添加的任何一门),以及悟道。它与 DaoEvents 并列而不取而代之。面向玩家的文档:天道。
HeavenlyDaoGainEvent 对每位打坐的玩家每打坐一秒触发一次(外加每挺过一道天劫落雷、每次晋阶与突破各一次),PersonalDaoComprehensionEvent 则在每次符合条件的击杀与每次功法施展时触发 —— 这两者的监听器都请保持轻量。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreHeavenlyDaoGainEvent | 是 | 天道的领悟进度即将推进。取消可回绝;用 setAmount 可重新缩放。 | player()、comprehension()、amount() / setAmount(float)。 |
HeavenlyDaoGainEvent | 否 | 天道的领悟进度已推进。amount 是实际施加的量(已计入监听器的缩放);total 是其后的值。 | player()、comprehension()、amount()、total()。 |
PreHeavenlyDaoRankChangeEvent | 是 | 玩家的天道品阶即将变更。取消则让他留在当前品阶 —— 底层的数值分毫不动,所以这只是压制了重新归类与昭告。 | player()、comprehension()、oldRank()、newRank()。 |
HeavenlyDaoRankChangeEvent | 否 | 玩家的天道品阶已变更(并已告知本人)。 | player()、comprehension()、oldRank()、newRank()。 |
PrePersonalDaoComprehensionEvent | 是 | 某门个人之道的领悟即将推进。取消可回绝;用 setAmount 可重新缩放。 | player()、comprehension()、dao()、amount() / setAmount(float)。 |
PersonalDaoComprehensionEvent | 否 | 某门个人之道的领悟已推进。amount 是实际施加的量;total 是其后的值。 | player()、comprehension()、dao()、amount()、total()。 |
PrePersonalDaoManifestEvent | 是 | 某门个人之道即将显化。取消则让它停在已领悟而未显化的状态。 | player()、comprehension()、dao()。 |
PersonalDaoManifestEvent | 否 | 某门个人之道为该玩家显化了。 | player()、comprehension()、dao()。 |
PersonalDaoSetAsideEvent | 否 | 一门已显化的个人之道被放下了。 | player()、comprehension()、dao()。 |
PreDaoEnlightenmentEvent | 是 | 一次悟道即将触发。取消即视同这次掷骰从未发生;用 setComprehensionGain 与 setQiGain 可重新缩放奖励。setQiGain 能压低灵气爆发,却无法把它抬过服务器的绝对上限 —— 该上限在本事件之前施加一次,读回 qiGain() 之后又施加一次。 | player()、comprehension()、subject()、comprehensionGain() / setComprehensionGain(float)、qiGain() / setQiGain(float)。 |
DaoEnlightenmentEvent | 否 | 一次悟道触发了。subject 是引发它的那门天道或个人之道。 | player()、comprehension()、subject()、comprehensionGain()、qiGain()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
道域
plugin.siren.API.DaoDomainEvents v0.11.1 —— 8 个事件(2 个可取消),涵盖修士以道域之心展开的那片锚定区域:展开、崩塌,以及敌对道域、首领的道域或敌对宗门大阵与之重叠时的交锋;此外还有首领道域与共鸣所需的生灵自己的展开与崩塌,以及盟友道域的配对。面向玩家的文档:道域,交锋部分见道域交锋。
这里的玩家与生灵以 UUID 而非 PlayerRef 标识:一方道域可能在其施放者的实体消失之后才崩塌。用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。element() 是施放者的大道元素;若道域是以天地灵气施放的(没有大道,或所修元素没有属于自己的风貌),则为 null。因施放者断线而造成的崩塌不触发任何事件:持有道域的实体已经不在,也没有什么会来察觉,其效果会在一秒之内自行消退。
每个监听器都在施放者的世界线程上运行(生灵事件则在生灵的世界线程上)。保持轻量,且不要在监听器里写入 Store。
此类中声明的枚举:
CollapseReason:EXPIRED—— 持续时间耗尽;LEFT_AREA—— 施放者走出了道域;DIED—— 施放者死亡(或化作逃遁的魂体);LEFT_WORLD—— 施放者换了世界,锚点不在他所处的世界里;GATE—— 道域进行中某道拒绝关口触发:打坐、突破途中、试炼、识海、庇护之所;DISABLED—— 道域(或功法使用)被关闭;CLASHED—— 该道域在与敌对道域或宗门大阵的交锋中落败,或与之打成平局(平局使双方道域皆碎裂)。为同一次交锋触发的DomainClashEvent,就在它之前。NpcDomainKind:CALAMITY—— 灾劫兽;EVENT_BOSS—— 活动世界首领;WARDEN—— 虚空裂隙守护者;ROGUE—— 元婴及以上的散修客;TEST—— 管理员在普通生灵身上设下的测试道域。NpcCollapseReason:EXPIRED—— 持续时间耗尽;LEFT_AREA—— 生灵走出自己道域的时间超过了宽限;DIED—— 生灵死亡;ENCOUNTER_ENDED—— 遭遇战结束或生灵被移出世界;DISABLED—— 首领道域、道域或功法被关闭;CLASHED—— 被玩家的道域击败或打成平局。它自成一个枚举,这样给CollapseReason添加常量就不会破坏穷举 switch。ResonanceMode:FULL—— 一种元素生养另一种;LESSER—— 天地灵气与元素道域谐和,威力减半。Outcome:FIRST_WON——first的交锋威势更高(对手是大阵时:道域胜过了大阵);SECOND_WON——second的交锋威势更高(对手是大阵时:大阵胜过了道域);TIE—— 威势相等。两方道域皆碎裂;道域对大阵时,只有道域碎裂,大阵屹立不倒。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreDomainUnfoldEvent | 是 | 一方道域即将展开:这次施放的各道关口都已通过,尚未扣任何灵气。取消则施放与被拒绝一样地失败 —— 不扣任何东西,不触发冷却,也没有道域 —— 并告知施放者有某种力量阻止了它。用 setRadius、setDurationSeconds 与 setQiCost 可重新调整。 | caster()、element()、tier()(0 为下限境界,1 为高一个境界,2 为高两个及以上)、radius() / setRadius(float)、durationSeconds() / setDurationSeconds(float)、qiCost() / setQiCost(float)(管理员绕过或创造模式的施放者为 0,他们分文不付)。 |
DomainUnfoldEvent | 否 | 道域立起。它在第一次脉冲之前宣告 —— 那次脉冲就可能裁决一场交锋、碎裂这方新道域,而监听器会先看到展开,再看到它所引发的崩塌。 | caster()、element()、tier()、radius()、durationSeconds()、qiSpent()。 |
DomainCollapseEvent | 否 | 一方道域结束。施放者断线时不触发。 | caster()、element()、reason()、secondsActive()。 |
DomainClashEvent | 否 | 两方敌对道域,或一方道域与一座敌对宗门大阵发生重叠,并已裁决出这场交锋。每次交锋触发一次,在它所引发的各个 DomainCollapseEvent 之前。 | first()(其脉冲发现了重叠的施放者 —— 通常是最后展开的那一位)、second()(对手是宗门大阵时为 null;管理员召出测试对手时,是一个不对应任何玩家的合成 id)、arraySect()(对手是大阵时为守方宗门的名字,否则为 null)、firstPower()、secondPower()(交锋威势,已含克制加成)、outcome()、counterDecided()(五行克制改变了结果时为 true:去掉加成,结果本会不同)。 |
PreNpcDomainUnfoldEvent | 是 | 一只生灵即将开始蓄势展开道域:越过了某个生命节点,或管理员的测试触发。取消则不展开(该节点已被消耗)。setRealmOrdinal、setRadius 与 setDurationSeconds 可重新调整,钳制在引擎认可的范围内。 | npc()(生灵的实体 UUID)、roleId()、kind()、element()(天地灵气为 null)、realmOrdinal() / setRealmOrdinal(int)、radius() / setRadius(float)、durationSeconds() / setDurationSeconds(float)。 |
NpcDomainUnfoldEvent | 否 | 生灵的道域在蓄势之后迸发。 | npc()、roleId()、kind()、element()、realmOrdinal()、radius()、durationSeconds()、worldName()、x()、y()、z()。 |
NpcDomainCollapseEvent | 否 | 生灵的道域结束;原因为 CLASHED 时,在引发它的 DomainClashEvent 之后。 | npc()、roleId()、kind()、element()、reason()、secondsActive()、shatteredBy()(获胜的玩家,否则为 null)、staggerSeconds()(不踉跄时为 0)。 |
DomainResonanceEvent | 否 | 两方盟友道域开始或停止共鸣。每位施放者各触发一次,从该施放者一侧看,所以一对真实玩家每次变化触发两次;管理员的测试回响只触发管理员一侧。施放者崩塌时,对每个伙伴都触发 started 为 false 的事件。 | caster()、partner()(测试回响为合成 id)、casterElement()、partnerElement()、mode()、casterFeeds()(LESSER 谐和中,天地灵气一方算作生养者)、started()。 |
声明为 @Nullable 的有:element()、casterElement() 与 partnerElement()(所有携带它们的事件);second();arraySect();shatteredBy()。
交锋按威势来裁决。一方道域的威势是其施放者的境界序号(炼体 0 至炼虚 6),若该道域的大道元素在五行相克中克制对方的元素,再加上克制加成;天地灵气的道域从不克制他人,也不被克制。宗门大阵的威势,取其配置的基础境界与领地内最强守方境界之高者,若其宗门的元素克制该道域的元素,同样再加上这一加成。威势更高者胜;威势相等为 TIE。交锋只发生在双方主人互视为敌人的道域之间 —— PvP 世界、斗法、正魔之战的对立一方,或其宗门之间一场正在进行的围攻 —— 绝不发生在盟友或中立者之间。
这些所覆写的配置键,都在 Arts/DaoDomainConfig.json:PreDomainUnfoldEvent.setRadius 对应 Domain-Radius 与 Domain-Radius-Per-Tier;setDurationSeconds 对应 Domain-Duration-Seconds 与 Domain-Duration-Per-Tier-Seconds;setQiCost 对应 Domain-Qi-Cost 与 Domain-Qi-Cost-Per-Tier。监听器留下的值在使用前会被限制范围 —— 半径 1 至 32 格,持续时间 1 至 25 秒,灵气不低于 0 —— 非有限的数字会被忽略,施放仍沿用它自己算出的值。DomainClashEvent 只读;其背后的数值是 Domain-Clash-Counter-Bonus(默认 1),由 Domain-Clash-Enabled 与 Domain-Clash-Arrays-Enabled 把关,共鸣中的施放者另加 Domain-Resonance-Clash-Bonus(默认 1)。对手是生灵的道域时,second() 为该生灵的实体 UUID。PreNpcDomainUnfoldEvent 重新调整的是 Npc-Domain-Boss-Radius、Npc-Domain-Boss-Duration-Seconds 与各境界键(Npc-Domain-Calamity-Realm 及其同类);门禁为 Npc-Domains-Enabled 与 Domain-Resonance-Enabled。整个系统的门禁:Dao-Domains-Enabled。
v0.11.1 没有 DaoSealEvents 这个类。道印的反应是在 Cultivation 自己的伤害管线里结算的,那里尚未设计任何钩子。扩展转而能观察的,是道印留下的各种编号:伤害类别 Cultivation_Seal_<Element>(共十个 —— 道印自身的命中,或被转化道印转化的原版符文)与 Cultivation_DaoReaction(反应的爆发),以及实体效果 Cultivation_SealMark_<Element>、Cultivation_SealBurst_<Element>、Cultivation_SealReaction_<Element> 与隐藏的 Cultivation_SealReaction_Cooldown。DaoElement.fromDamageCause(DamageCause) 沿着伤害类别的 Inherits 链把它归到元素:道印的伤害类别解析到它的元素,Cultivation_DaoReaction 则什么也解析不到 —— 见伤害类别与元素。完整清单,连同渐进式解锁、典籍与管理员的编号,见道印。
功法
plugin.siren.API.TechniqueEvents —— 15 个事件(7 个可取消),涵盖功法的施展与习得、两门合为第三门的合道、熟练度、御剑飞行的开关,以及计时战斗增益。面向玩家的文档:功法与秘籍。
对经由 CultivationAPI.registerTechnique 注册的第三方功法,这些事件与对内置功法完全一样地触发 —— 关卡、消耗与冷却的管线是共用的。
此类中声明的枚举:
BuffType:IRON_BODY—— 金刚不坏:固定的受伤减免;QI_INFUSION—— 真气灌注:输出伤害加成;QI_BARRIER—— 护体真气:吸收伤害的护盾池;CLOUD_STEP—— 疾风步:移动速度倍率。FlightStopReason:TOGGLE—— 他们自己关掉了它;QI_EXHAUSTED—— 飞行途中灵气耗尽;DEATH—— 他们死了;飞行状态被稳妥地清理掉。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreTechniquePerformEvent | 是 | 一门功法即将施展 —— 每道关卡都已通过。取消可静默回绝:不耗灵气,不进冷却。 | ref()、player()、technique()、qiCost() / setQiCost(float)、cooldownSeconds() / setCooldownSeconds(float)(小于等于 0 则不盖冷却戳)。 |
TechniquePerformEvent | 否 | 灵气已耗、冷却已盖戳、效果已运行。 | ref()、player()、technique()、qiCost()。 |
PreTechniqueLearnEvent | 是 | 一门功法即将被永久习得。取消可回绝之 —— 无论如何秘籍都会被消耗,正如一本传授已知功法的秘籍照样会被用掉。 | ref()、player()、techniqueId()。 |
TechniqueLearnEvent | 否 | 功法已习得。宗门所授的功法是实时解算的,永不触发此事件 —— 请改为监听宗门碑文事件。 | ref()、player()、techniqueId()。 |
PreSwordFlightStartEvent | 是 | 修士即将御剑升空。 | ref()、player()、horizontalSpeed() / setHorizontalSpeed(float)、verticalSpeed() / setVerticalSpeed(float)。 |
SwordFlightStartEvent | 否 | 他已凌空。 | ref()、player()、horizontalSpeed()、verticalSpeed()。 |
PreSwordFlightStopEvent | 是 | 修士即将落地。对 TOGGLE 取消是安全的,但取消一次 DEATH 落地会把飞行状态留在一具尸体上 —— 请按 reason() 加以判别。 | ref()、player()、reason()。 |
SwordFlightStopEvent | 否 | 他已落地;其坐骑(若有)也已消失。 | ref()、player()、reason()。 |
PreTechniqueBuffApplyEvent | 是 | 一项计时功法增益即将施加。 | ref()、player()、type()、durationSeconds() / setDurationSeconds(float)、magnitude() / setMagnitude(float)。 |
TechniqueBuffApplyEvent | 否 | 增益已生效。magnitude 表示该增益所度量的东西 —— 一个减伤百分比、一个伤害百分比、一个护盾池、一个速度倍率。 | ref()、player()、type()、durationSeconds()、magnitude()。 |
TechniqueBuffExpireEvent | 否 | 疾风步的速度倍率已被撤回,或因到期,或因清理。 | ref()、player()、type()。 |
PreTechniqueMasteryAdvanceEvent | 是 | 一门功法即将升上一级熟练阶。取消则让它停在原处 —— 经验与已研读的秘籍仍存着,所以只要它的任何情形再有变动,便会重新尝试。 | ref()、player()、techniqueId()、stage()(它正在升至的那一级)。 |
TechniqueMasteryAdvanceEvent | 否 | 一门功法的熟练度升了一阶。 | ref()、player()、techniqueId()、stage()。 |
PreTechniqueFusionEvent v0.8.0 | 是 | 一次合道即将尝试 —— 每一道关卡(两门母法皆臻顶峰、境界下限、灵气、冷却)都已通过。取消即无声回绝:不扣灵气、不记冷却、两门母法分毫无损。三个 setter 可在不改动 TechniqueConfig.json 的前提下,只为这一次尝试重新调参。 | ref()、player()、fusionId()、resultTechniqueId()、qiCost() / setQiCost(float)、consumeParents() / setConsumeParents(boolean)、failureChancePercent() / setFailureChancePercent(float)。 |
TechniqueFusionEvent v0.8.0 | 否 | 一次合道已成,结果功法已授予。 | ref()、player()、fusionId()、resultTechniqueId()。 |
声明为 @Nullable 的有:TechniqueLearnEvent、TechniqueBuffApplyEvent、TechniqueFusionEvent、TechniqueBuffExpireEvent、TechniqueMasteryAdvanceEvent、PreTechniqueLearnEvent、PreTechniqueBuffApplyEvent、PreTechniqueFusionEvent、PreTechniqueMasteryAdvanceEvent 上的 player()。
这些所覆写的配置键:PreTechniquePerformEvent 映照功法规则中各门功法自己的 Qi-Cost 与 Cooldown-Seconds 条目(见配置),以及指令页上的 /cultivation technique <id> 指令。PreTechniqueLearnEvent 会为玩家求得的每一门功法触发,无论出自哪一条解锁途径 —— 阅读秘籍、打坐中的顿悟、突破所开、宗门铭刻,或师父亲授 —— 故监听者无须理会究竟是哪一条。
一次合道是否消耗了两门母法,刻意不由 TechniqueFusionEvent 携带:请监听授予时触发的普通 TechniqueLearnEvent,并留意消耗型配方是经 TechniqueUnlockManager.revoke 移除母法的,而后者不触发自己的事件 —— 在正常玩法中,除了合道与管理员工具,没有任何东西会剥夺所学之物。
战斗深度
plugin.siren.API.CombatDepthEvents v0.10.1 —— 4 个事件(2 个可取消),涵盖功法被打断,以及元素克制占优时所发放的五行 PvP 奖励。破绽窗口不触发任何自己的事件 —— 它是战斗系统内部消耗的一个伤害倍率。面向玩家的文档:战斗深度。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreTechniqueInterruptEvent | 是 | 一位正在蓄力的修士所凝聚的功法即将被一记足够重的击打打断。取消可让蓄势不受打断地继续;setDamageAmount 可重新缩放带入配对后置事件的数值(此事件触发之后,打断本身仍会发生 —— 引发它的伤害早已落下)。 | ref()、player()、damageAmount() / setDamageAmount(float)。 |
TechniqueInterruptEvent | 否 | 一位蓄力的修士所凝聚的功法被一记足够重的击打打断了。damageAmount 是 PreTechniqueInterruptEvent 最终定下的(可能已重新缩放的)数值。 | ref()、player()、damageAmount()。 |
PreWuxingPvpRewardEvent | 是 | 一次五行克制占优的 PvP 击杀即将发放五行奖励。取消即拒发;用 setSpiritStones 可重新缩放实际授予的数量。 | killer()、killerPlayer()、spiritStones() / setSpiritStones(int)。 |
WuxingPvpRewardEvent | 否 | 一次五行克制占优的 PvP 击杀发放了五行奖励。 | killer()、killerPlayer()、spiritStones()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
天道誓言
plugin.siren.API.OathEvents v0.9.0 —— 8 个事件(4 个可取消),涵盖立下、违背与和平解除一道天道誓言,以及平复背誓所留下的道心破损。面向玩家的文档:天道誓言。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
FlawCleanseRoute:EXPIRED—— 其墙上时钟的计时自行走完;ITEM—— 消耗了一件平复之物;COMPANION—— 在所负誓约之人身旁打坐,提前将其烧尽。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreOathSwearEvent | 是 | 一份待决的邀约即将被接受,成为有约束力的誓言。取消可回绝 —— 无论如何这份邀约都已消耗,所以发起者须再发一份新的。 | offerer()、accepter()、type()、stake() / setStake(int)、sectId()。 |
OathSwornEvent | 否 | 一份待决邀约被接受,誓言就此立下(生效)。 | oathId()、type()、partyA()、partyB()、stake()、sectId()。 |
PreOathBreachEvent | 是 | 一道已立之誓即将被记为背誓,并施加惩罚。取消可径直赦免这次背誓(分毫不变 —— 无灵气损失、无业力、无道心破损);改用各 setter 则只是重新调整惩罚。 | oathId()、type()、breaker()、victim()、qiLossPercent() / setQiLossPercent(float)、karmaSwing() / setKarmaSwing(float)、flawDurationMinutes() / setFlawDurationMinutes(float)、flawSeverity() / setFlawSeverity(float)。 |
OathBreachEvent | 否 | 一道已立之誓被违背了,惩罚已经施加。 | oathId()、type()、breaker()、victim()、qiLost()、karmaGained()。 |
PreOathFlawCleanseEvent | 是 | 一处道心破损即将平复。取消可回绝这次尝试(物品若有,是否消耗仍由调用方决定 —— 见调用点)。 | player()、route()。 |
OathFlawCleanseEvent | 否 | 一位修士的道心破损经 route 途径平复了。 | player()、route()。 |
PreOathDissolveEvent | 是 | 一道已立之誓即将和平解除。取消则让它继续有效(不起变化 —— 提出的一方须再请求一次)。 | oathId()、type()、partyA()、partyB()。 |
OathDissolveEvent | 否 | 一道已立之誓和平解除了 —— 无惩罚,或是出于双方一致的 /cultivation oath dissolve,或是那一种由系统触发的无过错情形(见 OathManager.dissolveActiveOath)。 | oathId()、type()、partyA()、partyB()。 |
物品与炼制
掉落、丹药、灵核与秘籍,以及造出新物的诸般手艺:炼器、炼丹、锻造与符箓,外加兵器之中的灵。
物品
plugin.siren.API.ItemEvents —— 12 个事件(6 个可取消),涵盖修炼掉落、丹药、修行之核、秘籍与炼器。面向玩家的文档:聚灵采气、炼丹、秘籍、炼器。
从秘籍中习得功法会触发 TechniqueEvents 中的功法习得事件;传授天赋节点的秘籍则走 CultivationEvents 里的天赋解锁事件。本类涵盖的是秘籍物品本身。
此类中声明的枚举:
LootType:CULTIVATION_CORE—— 某一品阶的修行之核:灵核、玄核或神核(读itemId可知是哪一种);BEAST_EGG—— 灵兽蛋;SPIRIT_STONE—— 灵石,洞府供奉所用的通货;MANUAL—— 一本修炼秘籍;TREASURE_MATERIAL—— 在埋藏宝藏或遗迹宝库中找到的制作材料 —— 见plugin.siren.Utils.Treasure.TreasureCacheManager。RefinementOutcome:SUCCESS—— 兵器受了元素,抵达目标阶位;DESTROYED—— 尝试失败,兵器被毁;DEMOTED—— 尝试失败,兵器跌了一个阶位;FAILED—— 尝试失败却无伤大雅 —— 只损失了灵气。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreLootDropEvent | 是 | 一份修炼掉落即将交付。取消可拒绝它。 | ref()、player()、type()、itemId() / setItemId(String) —— 可整个替换成另一件物品。 |
LootDropEvent | 否 | 掉落已落入玩家背包并已昭告。判定未中、或物品放不下时永不触发。 | ref()、player()、type()、itemId()。 |
PreManualReadEvent | 是 | 一本秘籍即将授法。取消可回绝之 —— 无论如何秘籍都会被消耗。 | ref()、player()、techniqueId()(传授功法时有值)、skillNodeId()(传授节点时有值)。 |
ManualReadEvent | 否 | 秘籍已被阅读,其所授已施加。 | ref()、player()、techniqueId()、skillNodeId()。 |
PrePillConsumeEvent | 是 | 一枚灵丹即将生效。取消则该丹药不会被消耗。 | ref()、player()、effect() —— 该交互所配置的效果 id。 |
PillConsumeEvent | 否 | 丹药已服下,其药力已施加。 | ref()、player()、effect()。 |
PreSpiritCoreConsumeEvent | 是 | 一枚修行之核即将被吸收。取消则该核不会被消耗。 | ref()、player()、qi() / setQi(float)(打坐加成已折入其中)、meditating()。 |
SpiritCoreConsumeEvent | 否 | 核已被吸收。 | ref()、player()、qi() —— 实际入账的量。 |
PreRefinementStartEvent | 是 | 一场炼器仪式即将开始。取消则不耗灵气。 | ref()、player()、element()、targetTier()、qiCost() / setQiCost(float)。 |
RefinementStartEvent | 否 | 仪式已开始;灵气已耗,修士已落座。 | ref()、player()、element()、targetTier()、qiCost()。 |
PreRefinementCompleteEvent | 是 | 一场炼器仪式即将结算。取消可静默中止 —— 兵器分毫不动,但预先付出的灵气仍是耗掉了。 | ref()、player()、element()、targetTier()、successChance() / setSuccessChance(float) —— 填 1 必成,填 0 必败。 |
RefinementCompleteEvent | 否 | 仪式已结算。 | ref()、player()、element()、targetTier()、outcome()、stack() —— 事后的兵器,若已毁则为 null。 |
声明为 @Nullable 的有:LootDropEvent、PreLootDropEvent 上的 player();techniqueId()(所有携带它的事件);skillNodeId()(所有携带它的事件);stack()。
这些所覆写的配置键:PreLootDropEvent 对应各项掉落概率键(Spirit-Core-Drop-Chance、Profound-Core-Drop-Chance、Divine-Core-Drop-Chance、Egg-Kill-Drop-Chance、SpiritStone-Kill-Drop-Chance、Manual-Tribulation-Drop-Chance、Manual-Player-Kill-Drop-Chance);PreSpiritCoreConsumeEvent.setQi 对应 Spirit-Core-Qi-Value / Profound-Core-Qi-Value / Divine-Core-Qi-Value 与 Meditation-Core-Bonus-Multiplier;PreRefinementStartEvent.setQiCost 对应 Refinement-Base-Qi-Cost 与 Refinement-Qi-Cost-Tier-Multiplier;PreRefinementCompleteEvent.setSuccessChance 对应 Refinement-Base-Success-Chance、Refinement-Success-Chance-Loss-Per-Tier 与 Refinement-Min-Success-Chance。
炼丹
plugin.siren.API.AlchemyEvents v0.10.0 —— 5 个事件(2 个可取消),涵盖丹炉的炼制仪式 —— 开始、结算,以及沿途的火候照看提示。它与 ItemEvents.PillConsumeEvent 互为补充,后者涵盖的是服下一枚成丹,而非炼制一枚。面向玩家的文档:炼丹。
此类中声明的枚举:
RefineOutcome:SUCCESS;FAILED—— 彻底失败:白白耗掉所用的灵草与灵气,别无他事发生;BOTCH—— 失败,且丹炉反噬了炼丹者 —— 见 AlchemyConfig 的Refine-Botch-*字段。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreRefineStartEvent | 是 | 一场炼制仪式即将开始。取消可回绝(不耗灵草与灵气)。 | ref()、player()、effect()、durationSeconds() / setDurationSeconds(float)。 |
RefineStartEvent | 否 | 一场炼制仪式开始了;灵草与灵气下限的检查早已通过。 | ref()、player()、effect()、qiDrainPerSecond()。 |
PreRefineCompleteEvent | 是 | 一场炼制仪式即将结算出品阶。取消可静默中止 —— 灵草与灵气照样耗掉,不产出任何东西,与 ItemEvents.PreRefinementCompleteEvent 和 TalismanEvents.PreInscribeCompleteEvent 所用的形态相同。各 setter 重新权衡品阶掷骰实际用到的输入(灵草品质、熟练度与火候调整)。仅在自然完成时触发,被打断时绝不触发。 | ref()、player()、effect()、herbQualityAvg() / setHerbQualityAvg(float)、masteryLadderFraction() / setMasteryLadderFraction(float)、tendDelta() / setTendDelta(float)。 |
RefineCompleteEvent | 否 | 一场炼制仪式结算了。除非 outcome 为 SUCCESS,否则 grade 为 null。 | ref()、player()、effect()、outcome()、grade()。 |
TendPromptResolvedEvent | 否 | 一次火候照看提示被处理了 —— 应答(迅捷或稳当)、错过或失手 —— 发生在一场进行中的炼制仪式里。promptIndex 从 0 起算(这是本场仪式送出的第 N 条提示);promptCount 是该仪式所配置的 Tend-Prompts-Max 上限,并非已经触发了多少条。 | ref()、player()、action()、outcome()、promptIndex()、promptCount()。 |
声明为 @Nullable 的有:grade()。
锻造
plugin.siren.API.ForgingEvents v0.9.1 —— 2 个事件(1 个可取消),涵盖在锻造台上淬炼一件已造好的修炼兵器或护甲 —— 成功、失败与反噬三种结果。面向玩家的文档:锻造。
此类中声明的枚举:
ForgeOutcome:SUCCESS;FAILED—— 彻底失败:白白耗掉所用的材料,且若 Forge-Demote-On-Fail-From-Tier 如此规定,物品还会降一阶;BOTCH—— 失败,且锻炉反噬了锻造者 —— 见 ForgingConfig 的Forge-Botch-*字段。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreForgeEvent | 是 | 一次锻造尝试即将开始 —— 所有检查都已通过,但材料和物品都还没被动过。取消可彻底回绝;什么都不扣,也不会启动仪式。 | ref()、player()、itemId()、targetTier()。 |
ForgeCompleteEvent | 否 | 一次锻造尝试结算了。除非 outcome 为 SUCCESS,否则 grade 为 null。resultStack 是物品此刻的样子(已锻、已降阶或不变)—— 仅当修士的背包里无处放回时才为 null(见 ForgingManager.placeItem),随之而来的玩家消息已会如此告知。 | ref()、player()、targetTier()、outcome()、grade()、resultStack()。 |
声明为 @Nullable 的有:grade();resultStack()。
符箓
plugin.siren.API.TalismanEvents v0.9.0 —— 6 个事件(3 个可取消),涵盖在符箓案前刻画(开始与完成,结果有成功、失败与反噬)以及使用一张成品符箓。面向玩家的文档:符箓。
此类中声明的枚举:
InscribeOutcome:SUCCESS;FAILED—— 彻底失败:白白耗掉所用的材料与灵气,别无他事发生;BOTCH—— 失败,且符火反噬了刻画者 —— 见 TalismanConfig 的Inscribe-Botch-*字段。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreInscribeStartEvent | 是 | 一场刻画仪式即将开始。取消可回绝(不耗材料与灵气)。 | ref()、player()、talismanId()、element()。 |
InscribeStartEvent | 否 | 一场刻画仪式开始了;材料与灵气下限的检查早已通过。 | ref()、player()、talismanId()、element()、qiDrainPerSecond()。 |
PreInscribeCompleteEvent | 是 | 一场刻画仪式即将结算出品阶。取消可静默中止 —— 材料与灵气已然沉没,不产出任何东西,与 ItemEvents.PreRefinementCompleteEvent 所用的形态相同。各 setter 重新权衡品阶掷骰实际用到的两项输入,这是扩展改动符箓品阶几率的受支持做法(例如仅为这一次掷骰加一份固定的亲和加成),而无须触碰已存的大道。仅在自然完成时触发,被打断时绝不触发。 | ref()、player()、talismanId()、element()、masteryLadderFraction() / setMasteryLadderFraction(float)、affinityFraction() / setAffinityFraction(float)。 |
InscribeCompleteEvent | 否 | 一场刻画仪式结算了。除非 outcome 为 SUCCESS,否则 grade / stack 为 null。 | ref()、player()、talismanId()、element()、outcome()、grade()、stack()。 |
PreTalismanUseEvent | 是 | 一张符箓即将被使用。取消可回绝(不消耗这一次使用次数)。 | ref()、player()、talismanId()、grade()。 |
TalismanUseEvent | 否 | 一张符箓被使用,其效果已施加。remainingCharges 是这次使用之后剩下的次数 —— 降到 0 时这叠符箓即告消失。 | ref()、player()、talismanId()、grade()、remainingCharges()。 |
声明为 @Nullable 的有:InscribeCompleteEvent 上的 grade();stack()。
器灵
plugin.siren.API.WeaponSpiritEvents v0.9.0 —— 6 个事件(3 个可取消),涵盖一件本命法宝的器灵苏醒、升级,以及经 /cultivation spirit nurture 以灵气喂养。每个事件都携带当前主人的 PlayerRef。面向玩家的文档:器灵。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreWeaponSpiritAwakenEvent | 是 | 一件兵器的器灵即将苏醒 —— 炼数与击杀两道门槛皆已达成。取消可让它恰好停在门槛上;已存的击杀数分毫不动,所以下一次符合条件的击杀会再度触发此事件。 | owner()、item()、killsAtAwaken()。 |
WeaponSpiritAwakenEvent | 否 | 一件兵器的器灵刚刚苏醒;item 是苏醒写入之后的那一叠。 | owner()、item()、killsAtAwaken()。 |
PreWeaponSpiritLevelUpEvent | 是 | 一件兵器的器灵即将升级。取消可让它停在当前等级(经验仍会存下)。 | owner()、item()、oldLevel()、newLevel()。 |
WeaponSpiritLevelUpEvent | 否 | 一件兵器的器灵刚刚升了一级;item 是升级写入之后的那一叠。 | owner()、item()、newLevel()、reachedMaturity()。 |
PreWeaponSpiritNurtureEvent | 是 | 玩家即将以灵气喂养他的器灵。取消可彻底回绝这次喂养(不耗灵气、不得经验)。setQiToConvert 改变所献灵气中有多少被转化;WeaponSpirit-Nurture-Max-Qi-Per-Use 默认就是在这里施加的,所以扩展应当调整这个字段,而不是配置。 | owner()、item()、qiToConvert() / setQiToConvert(float)。 |
WeaponSpiritNurtureEvent | 否 | 玩家刚刚以灵气喂养了他的器灵;每次成功的 nurture 调用触发一次,无论它是否同时让器灵升了级。 | owner()、item()、qiConverted()、xpGained()。 |
灵兽
伙伴,以及繁育出新伙伴的过程。
灵兽
plugin.siren.API.BeastEvents —— 20 个事件(10 个可取消),涵盖收服、孵化、结契、召唤与伙伴自身的修行,并自 0.7.2 起涵盖它的兽技、进化与坐骑,以及灵兽巢穴所孕育的一窝幼兽。面向玩家的文档:灵兽。
此类中声明的枚举:
BindSource:TAME—— 在野外降伏并收服;HATCH—— 由灵兽蛋孵化而来;DEN—— 从一座备齐供品的灵兽巢穴中认领。DismissReason:DISMISSED—— 遣归,所修一概不损;RELEASED—— 永久放归,契约就此断绝;EXPEDITION—— 派去历练:所修一概不损,计时一满便回来。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreBeastTameAttemptEvent | 是 | 一次收服判定即将掷出。取消可直接回绝这次尝试 —— 不耗符箓。 | ref()、player()、species()、chance() / setChance(float) —— 0–1,已计入境界与道之共鸣的加权。 |
BeastTameAttemptEvent | 否 | 判定已结算。 | ref()、player()、species()、chance()、success()。 |
PreBeastBindEvent | 是 | 一头伙伴即将结契。取消则修士保留他原有的灵兽 —— 符箓或蛋照样耗掉。 | ref()、player()、species()、source()。 |
BeastBindEvent | 否 | 伙伴已结契,取代此前的那一头。 | ref()、player()、species()、source()。 |
PreBeastSummonEvent | 是 | 伙伴之身即将生成。取消则玩家会被告知召唤失败。 | owner()、player()、species()。 |
BeastSummonEvent | 否 | 其身已生成于主人身侧。 | owner()、player()、beast()(生成的实体)、species()。 |
PreBeastDismissEvent | 是 | 伙伴即将被遣归或放归。 | owner()、player()、reason()。 |
BeastDismissEvent | 否 | 其身已离世间。 | owner()、player()、reason()。 |
PreBeastXpGainEvent | 是 | 伙伴即将获得经验。对每一处来源皆触发 —— 打坐分成、击杀与亲手喂食一视同仁。 | owner()、player()、beast()(当前的 SpiritBeastComponent —— 境界、阶段、已存经验)、amount() / setAmount(float)。 |
BeastXpGainEvent | 否 | 经验已入账。 | owner()、player()、amount()、stagesGained()(只存了进度时为 0)。 |
PreBeastAdvanceEvent | 是 | 伙伴即将进阶一个阶段。取消可把它按在原处 —— 那一阶段的经验已经花掉了,因此这会让它白丢那份进度。 | owner()、player()、fromRealm()、fromStage()。 |
BeastAdvanceEvent | 否 | 伙伴已进阶。每一阶段触发一次。 | owner()、player()、realm()、stage()。 |
PreBeastArtEvent | 是 | 一头伙伴即将施展一门兽技。取消可制止它 —— 冷却只在效果真正运行之后才盖戳,所以被否决的兽技不让灵兽损失任何东西,它会在下一次得空时重试。 | owner()、player()、beast()、art()、commanded()(灵兽自己选的则为 false)。 |
BeastArtEvent | 否 | 一头伙伴施展了它的一门兽技。 | owner()、player()、beast()、art()、commanded()。 |
PreBeastEvolveEvent | 是 | 一头伙伴即将接受进化仪式。此时灵气尚未被取走,所以否决不让修士损失任何东西。 | owner()、player()、beast()、from()、to()、successChance() / setSuccessChance(float)。 |
BeastEvolveEvent | 否 | 仪式结算了。succeeded() 表明结果走向,失败时 to() 为 null。 | owner()、player()、beast()、from()、to()、succeeded()。 |
PreBeastMountEvent | 是 | 一头伙伴即将以可骑乘之身被召出。取消可回绝坐骑。 | owner()、player()、beast()、species()。 |
BeastMountEvent | 否 | 伙伴以可骑乘之身被召出了。 | owner()、player()、beast()、species()。 |
PreBeastDenBroodEvent | 是 | 一座灵兽巢穴即将掷出一窝。取消则让巢穴没有这一窝 —— 下次它的评估扫描运行时会再试。此时尚未持久化任何东西,所以否决不让供养者损失任何东西。 | world()、x()、y()、z()、species()、appraisalScore()。 |
BeastDenBroodEvent | 否 | 一座灵兽巢穴掷出了一窝,待到期后供人认领。 | world()、x()、y()、z()、species()、appraisalScore()。 |
声明为 @Nullable 的有:player()(所有携带它的事件);BeastEvolveEvent 上的 to()。
这些所覆写的配置键:PreBeastTameAttemptEvent.setChance 对应 Tame-Chance-Bonus-Per-Realm、Tame-Chance-Element-Match-Bonus 与 Tame-Chance-Max(由 Tame-Consume-Talisman-On-Failure 决定失手的代价);PreBeastXpGainEvent.setAmount 对应 Beast-Xp-Per-Kill、Beast-Xp-Own-Kill-Multiplier 与 Beast-Xp-Per-Qi-Item-Point。整套系统的门禁:Beasts-Enabled;Beast-Arts-Enabled、Beast-Evolution-Enabled 与 Beast-Mounts-Enabled 则分别控制 0.7.2 新增的三项系统。
灵兽繁育
plugin.siren.API.BreedingEvents v0.9.0 —— 4 个事件(2 个可取消),涵盖两位修士在灵兽栏中产出一枚蛋的仪式,以及把繁育所得的蛋孵化成结契的伙伴。一枚繁育所得的蛋孵化时仍会触发 BeastEvents.BeastBindEvent。面向玩家的文档:灵兽。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreBeastBreedEvent | 是 | 一场繁育仪式即将落到两位修士身上 —— 在二人都确认位于同一兽栏、灵气足够之后、任何一方的灵气被动用之前触发。取消可直接回绝;此时尚未花费任何东西。 | offerer()、accepter()、parentA()、parentB()。 |
BeastBreedEvent | 否 | 一场繁育仪式完成,并为 recipient(发出邀约的一方)产下一枚蛋。只触发一次,出自仪式自身的完成,而非邀约或接受。 | recipient()、partner()、parentA()、parentB()、offspring()、quality()。 |
PreBeastEggHatchEvent | 是 | 一枚繁育所得的蛋即将孵化。取消可回绝 —— 蛋不会被消耗,与休眠的野生孵化蛋一致(见 BeastEggHatchInteraction 的繁育分支)。 | ref()、player()、offspring()、metadata()。 |
BeastEggHatchEvent | 否 | 一枚繁育所得的蛋孵化成了结契的伙伴。 | ref()、player()、offspring()、metadata()。 |
声明为 @Nullable 的有:partner();player()(所有携带它的事件)。
宗门、坊市与同道
宗门与宗门之间的战事,被围宗门的战时大阵,侍奉大殿的人,功德,队伍与道侣,拍卖行与悬赏令。
宗门
plugin.siren.API.SectEvents —— 41 个事件(18 个可取消),涵盖开宗、解散、门籍、职位、简称、大殿、大殿灵脉、殿上碑文、旗帜、外交与宗门藏书阁。面向玩家的文档:宗门,以及指令页上的 /sect 系列。
监听器持有 SectManager 的锁 —— 见注册与线程。这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
JoinMethod:INVITE—— 他们接受了一份待决邀约;OPEN—— 他们走进了一个 OPEN 的宗门;REQUEST—— 管理者批准了他们待决的入门申请。LeaveReason:LEFT—— 他们自行离去;KICKED—— 宗主或长老将他们逐出。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreSectCreateEvent | 是 | 玩家即将开宗立派。取消后它会报告创立被回绝。 | leader()、name() / setName(String) —— 事后仍会重新校验形状与唯一性。 |
SectCreateEvent | 否 | 宗门已创立并已建索引。 | leader()、sect()。 |
PreSectDisbandEvent | 是 | 宗门即将解散。取消可保其不倒。 | leader()、sect()。 |
SectDisbandEvent | 否 | 门人索引已解除、阵法已释放。sect 是那个已成孤儿的对象,仍可读取其最后的名录。 | leader()、sect()。 |
PreSectInviteEvent | 是 | 一份邀约即将发出。 | inviter()、invitee()、sect()、expiryMillis() / setExpiryMillis(long) —— 其失效的墙上时钟毫秒数。 |
SectInviteEvent | 否 | 邀约处于未决状态,尚未被接受。 | inviter()、invitee()、sect()。 |
PreSectJoinEvent | 是 | 玩家即将入门。取消后邀约或申请仍存续,因此他可以再试。 | player()、sect()、method()。 |
SectJoinEvent | 否 | 他已在名录之上。 | player()、sect()、method()。 |
PreSectLeaveEvent | 是 | 玩家即将离去或被逐。取消可把他留在名录上。 | player()、sect()、reason()、actor()。 |
SectLeaveEvent | 否 | 他已不在名录上。KICKED 时 actor 是执行驱逐者,LEFT 时则是玩家本人。 | player()、sect()、reason()、actor()。 |
PreSectJoinRequestEvent | 是 | 一份入门申请即将排入某个 REQUEST 规矩的宗门。 | player()、sect()。 |
SectJoinRequestEvent | 否 | 申请已排入队列。 | player()、sect()。 |
SectJoinRequestDeniedEvent | 否 | 管理者驳回了一份未决申请。 | manager()、applicant()、sect()。 |
PreSectRankChangeEvent | 是 | 长老职位即将变更。 | leader()、target()、sect()、promoted() —— 由弟子擢升为长老时为 true。 |
SectRankChangeEvent | 否 | 职位已变更。 | leader()、target()、sect()、promoted()。 |
PreSectMottoChangeEvent | 是 | 宗训即将设定。 | manager()、sect()、oldMotto()、motto() / setMotto(String) —— 事后仍适用 60 字符上限。 |
SectMottoChangeEvent | 否 | 宗训已替换。 | manager()、sect()、oldMotto()、newMotto()。 |
PreSectJoinPolicyChangeEvent | 是 | 入门规矩即将变更。 | leader()、sect()、oldPolicy()、policy() / setPolicy(Sect.JoinPolicy)。 |
SectJoinPolicyChangeEvent | 否 | 规矩已变更。 | leader()、sect()、oldPolicy()、newPolicy()。 |
PreSectRenameEvent | 是 | 宗门即将改名。 | leader()、sect()、oldName()、newName() / setNewName(String) —— 事后仍会重新校验。 |
SectRenameEvent | 否 | 已改名;阵法、山门灵泉与未决邀约都已随之带过。 | leader()、sect()、oldName()、newName()。 |
PreSectInscriptionChangeEvent | 是 | 殿上碑文即将变更。 | leader()、sect()、oldTechniqueId()、newTechniqueId() / setNewTechniqueId(String) —— 传空则将其抹去。 |
SectInscriptionChangeEvent | 否 | 碑文已变更。 | leader()、sect()、oldTechniqueId()、newTechniqueId()。 |
PreSectHallClaimEvent | 是 | 大殿即将设立。取消后它会报告该区块已被占据。 | leader()、sect()、world()、chunkX()、chunkZ()、veinTier()。 |
SectHallClaimEvent | 否 | 宗门已在一条灵脉上设立或迁移了大殿。 | leader()、sect()、world()、chunkX()、chunkZ()、veinTier()。 |
PreSectHallCaptureEvent | 是 | 大殿即将易主给得胜的围攻方。取消可让它留在守方手中 —— 围攻仍判为胜。 | attacker()、defender()、world()、chunkX()、chunkZ()、veinTier()。 |
SectHallCaptureEvent | 否 | 一场获胜的围攻已移交大殿;守方现已无殿。 | attacker()、defender()、world()、chunkX()、chunkZ()、veinTier()。 |
SectVeinAscendedEvent v0.11.2 | 否 | 宗门的大殿灵脉由丰沛升华为龙脉(见宗门灵脉)。龙脉是挂在宗门身上的叠加层,绝不会写入区块自身的灵脉,所以世界本身并未改变。在清扫线程上、SectManager 的监视器之内触发:读取后交接出去。没有前置事件;何时发生由宗门自己的计时决定。 | sect()、world()、chunkX()、chunkZ()。 |
PreSectBannerChangeEvent | 是 | 宗门的旗帜即将变更。取消可让旧旗继续飘扬。监听器改写该 id 之后,它不会被重新校验 —— 一个未注册的 id 并非错误,只会解算为对应灵脉品阶的默认灯火。 | manager()、sect()、oldBannerId()、bannerId() / setBannerId(String)。 |
SectBannerChangeEvent | 否 | 旗帜已变更。大殿的常置灯火会在其下一次脉动时切换为新旗。 | manager()、sect()、oldBannerId()、newBannerId()。 |
PreSectAbbreviationChangeEvent v0.8.0 | 是 | 一宗的简称即将变更。取消即回绝;setAbbreviation 可改写它 —— 3–6 个字母/数字的规则与全服唯一性检查仍会在其后照常执行。 | leader()、sect()、oldAbbreviation()、abbreviation() / setAbbreviation(String)。 |
SectAbbreviationChangeEvent v0.8.0 | 否 | 简称已变更。 | leader()、sect()、oldAbbreviation()、newAbbreviation()。 |
SectAllianceFormedEvent | 否 | 两个宗门结成了同盟。actor 是接受提议的人。 | actor()、sectA()、sectB()。 |
SectAllianceBrokenEvent | 否 | 一份既有的同盟终止了;任何一方的宗主都可单方面解除。actor 是解除者。 | actor()、sectA()、sectB()。 |
SectRelationChangedEvent | 否 | 两宗之间的 NON_AGGRESSION(互不侵犯)或 TRADE(通商)关系结成或终止。ALLIANCE 永不触发它:上面那一对同盟事件已覆盖那一级,所以同时监听二者的监听器不会被重复通知。formed 在关系刚刚开始时为 true。 | actor()、sectA()、sectB()、kind()、formed()。 |
PreSectLibraryResearchStartEvent | 是 | 宗门藏书阁即将开始研究新的课题。取消则让它继续研究原来的东西(或什么都不研究)。 | actor()、sect()、oldTechniqueId()、newTechniqueId()。 |
SectLibraryResearchStartEvent | 否 | 宗门藏书阁开始研究新的课题(取代它此前所研究的东西,如果有的话)。 | actor()、sect()、techniqueId()。 |
PreSectLibraryCompileEvent | 是 | 宗门藏书阁即将编成一门独门功法。取消则把它拦在门口 —— 进度保持在耗费之上,下一次结算时再度触发。 | sect()、techniqueId()。 |
SectLibraryCompileEvent | 否 | 宗门藏书阁编成了一本独门功法秘籍。 | sect()、techniqueId()。 |
PreSectLibraryRedeemEvent | 是 | 一名门人即将兑取他那份已编成的藏书阁秘籍。取消可回绝(不标记为已兑取,故可重试);用 setManualItemId 可换成另一件物品。 | member()、sect()、techniqueId()、manualItemId() / setManualItemId(String)。 |
SectLibraryRedeemEvent | 否 | 一名门人兑取了自己那份已编成的藏书阁秘籍。 | member()、sect()、techniqueId()、manualItemId()。 |
这些所覆写的配置键:PreSectInviteEvent.setExpiryMillis 对应 Sect-Invite-Expiry-Seconds;大殿的设立受 Sect-Hall-Min-Vein-Tier 管辖(v0.11.2 并由 Sect-Hall-Claim-Anywhere 在任意土地上豁免);碑文受 Sect-Inscription-Enabled 管辖;整个子系统受 Sects-Enabled 与 Sect-Max-Members 管辖。旗帜事件所携带的旗帜 id,皆取自旗帜注册表 —— 六种内置旗帜,外加任何扩展经由 registerSectBanner 添加的旗帜。
战事
plugin.siren.API.WarEvents —— 9 个事件(4 个可取消),涵盖向敌方大殿宣布围攻、它如何结算、阵法 2.0 的攻城旗,以及盟宗增援所赚得的奖励。面向玩家的文档:宗门攻伐。
一场围攻要么是镇压(Suppress,默认:获胜绝不会让大殿易主,因此不触发夺取事件),要么是征服(Conquest),获胜时经 SectManager.captureHall 移交大殿。那次移交就是 SectEvents.PreSectHallCaptureEvent 与 SectHallCaptureEvent:否决其中的前置事件,即可让征服获胜而大殿不动。这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
SiegeFailReason:LAPSED—— 攻方未能在 CONTEST 窗口耗尽之前占据大殿足够久;DEFENDER_GONE—— 检查时,攻方或守方宗门(或守方大殿)已不复存在;MUSTER_FAILED—— MUSTER 的期限已过,而双方未能凑齐各自的最低在场人数 —— 彻底无事发生,守方也不进冷却;DEFENDER_ABSENT—— CONTEST 被强制叫停:大殿所在世界中守方的实时在场人数在宽限期过后仍为零 —— 以守方胜出了结,守方无损;ABORTED—— 管理员或 Wars-Enabled 总开关径直取消了围攻 —— 对双方都不产生后果,攻方的宣战花费也予以退还。BannerBreakSide:ATTACKER;DEFENDER;THIRD_PARTY。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreWarDeclareEvent | 是 | 一场围攻即将宣布。取消后调用方会被告知战事系统已禁用。 | attacker()、defender()、windowMillis() / setWindowMillis(long) —— 攻方有多久去完成其占据。 |
WarDeclareEvent | 否 | 围攻已生效,双方均已收到告知。 | attacker()、defender()、siege()。 |
PreSiegeCaptureEvent | 是 | 一场围攻即将获胜。取消可让它继续进行 —— 攻方仍在占据,并会在其下一个在场判定周期再次触发此事件,因此请仅在你自己的某个条件尚未满足时取消。 | attacker()、defender()、siege()。 |
SiegeCaptureEvent | 否 | 攻方已占据足够久。大殿的移交已经尝试过,守方的免战冷却也已开始。 | attacker()、defender()、siege()。 |
SiegeFailEvent | 否 | 围攻结束,大殿仍在守方手中。 | siege()、reason()。 |
PreSiegeBannerPlaceEvent | 是 | 阵法 2.0:一面攻城旗即将被安放。取消可回绝(安放者会被告知有东西阻止了此处安放)。在取任何监视器之前触发,所以不持有任何锁,监听器可以读取 WarManager 的状态;登记上限与围攻是否仍在进行,会在其后重新权威核对。 | attackerSect()、defenderSect()、world()、x()、y()、z()。 |
SiegeBannerPlaceEvent | 否 | 阵法 2.0:一面攻城旗已安放,此刻正立着。 | banner()。 |
SiegeBannerBreakEvent | 否 | 阵法 2.0:一面攻城旗被毁 —— 无论何人所毁,不受保护。breakerSide 表明毁旗者(如有)属于哪一方。 | banner()、breaker()、breakerSide()。 |
PreWarReinforcementRewardEvent | 是 | 一个盟宗对成功守住(LAPSED)的围攻所作的增援,即将获得奖励。取消则扣下这一个盟友的奖励,而不影响任何其他合格的盟友;每个增援宗门各有一个自己的事件。setContributionPerMember 只重新缩放这一份发放。 | reinforcingSect()、defender()、siege()、contributionPerMember() / setContributionPerMember(int)。 |
这些所覆写的配置键:PreWarDeclareEvent.setWindowMillis 对应 War-Window-Seconds;相关键还有 War-Required-Hold-Seconds、War-Cooldown-Hours、War-Defender-Grace-Seconds、War-Requires-Defender-Online 以及 Wars-Enabled 这道门禁。
宗门大阵
plugin.siren.API.SectArrayEvents v0.11.1 —— 3 个事件(1 个可取消),涵盖被围宗门在自家所占地界上升起的战时护佑:宗主或一位长老从自己的余额里付出贡献点,大阵一直撑到围攻了结,并以五种缘由之一撤下。它不放置任何方块,也不生成任何实体 —— 只有实体效果、边界粒子与声响。面向玩家的文档:宗门大阵。
宗门是活的 Sect 对象,与 SectEvents 交出来的完全一样:读走你要的东西然后返回。不要在监听器里回头调用大阵的升起或撤下。升起者是 UUID 而非 PlayerRef,因为在后续事件被读取时,他可能已经离线;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
管理员用测试指令升起的大阵,跳过战时与代价两道关口。它会触发 SectArrayRaisedEvent(adminRaised() 为 true),但绝不触发 PreSectArrayRaiseEvent,后者只属于要花钱的游戏内升起。
此类中声明的枚举:
EndReason:SIEGE_ENDED—— 针对该宗门的围攻已了结 —— 得胜、落败、战期耗尽或被取消。最常见的结束。被取消的围攻(管理员取消,或攻伐系统被关闭)还会把升起者所付的贡献点退还给他;HALL_LOST—— 该宗门不再持有大殿(被征服夺走)或已不复存在(已解散);LOWERED—— 宗主或长老用/sect array lower撤下。概不退还;ADMIN—— 管理员用/cultivation admin array lower撤下,或管理员升起的测试大阵到了配置的存续时限(Sect-Array-Admin-Test-Minutes);DISABLED—— 宗门大阵(或宗门系统)在配置里被关闭。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreSectArrayRaiseEvent | 是 | 宗主或长老即将升起大阵。所有关口都已通过 —— 功能已开启,有一场围攻正针对该宗门,宗门持有大殿而尚无大阵,升起者付得起配置的代价 —— 但尚未花费任何东西。取消则升起失败,回话是一句泛泛的「此刻有某种力量阻止了这一操作」:不扣任何东西,也没有大阵。用 setCost 可重新调整代价(比如为持有某件圣物的宗门打折);留下的值会被限制在 0 至 1,000,000,升起者仍须付得起,否则升起以贡献点不足而失败。针对配置代价的检查先于本事件进行,所以打折能降低扣款,却救不了本来就付不起配置代价的升起者。 | sect()、raiser()、cost() / setCost(int) —— 从升起者自己的余额里扣的贡献点。 |
SectArrayRaisedEvent | 否 | 大阵升起了。 | sect()、raiser()(管理员升起时为 null)、cost()(实际扣下的贡献点;管理员升起为 0)、adminRaised()。 |
SectArrayEndedEvent | 否 | 大阵撤下了。 | sect()(HALL_LOST 时,它的名字可能已不在名册里)、reason()、secondsActive()。 |
声明为 @Nullable 的有:raiser()(仅限 SectArrayRaisedEvent)。
升起事件在升起者的指令线程上触发;结束事件则在最先察觉到结束的那条线程上触发 —— 某个世界每秒一次的守阵机制,或撤下它的那条指令 —— 所以它不绑定于该宗门自己的世界。三个事件都在 SectArrayManager 自己的监视器之外触发。
这些所覆写的配置键,都在 Society/SectArrayConfig.json:PreSectArrayRaiseEvent.setCost 对应 Sect-Array-Cost-Contribution(默认 100)。相关键有 Sect-Array-Defender-Damage-Reduction-Percent、Sect-Array-Siege-Slow-Percent、Sect-Array-Base-Realm、Sect-Array-Border-Seconds、Sect-Array-Border-Max-Posts 与 Sect-Array-Admin-Test-Minutes。整个系统的门禁:Sect-Array-Enabled。大阵与道域之间的交锋,由 DaoDomainEvents.DomainClashEvent 上报,不在这里。
护山傀儡
plugin.siren.API.GuardianEvents v0.10.2 —— 4 个事件(1 个可取消),涵盖在宗门大殿派驻一尊护山傀儡、其中一尊倒下,以及最后一尊倒下。派驻可以取消。面向玩家的文档:宗门。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreSectGuardianStationEvent | 是 | 一名门人即将派驻一处新的护山傀儡岗位。取消可回绝(对执行者而言,表现为派驻尝试直接失败)—— 在 SectGuardianManager.station 中所有关卡都通过之后、贡献消耗被扣之前触发,所以否决不让执行者损失任何东西。 | sect()、actor()、postIndex()。 |
SectGuardianStationedEvent | 否 | 一名门人成功在其宗门大殿派驻了一处新的护山傀儡岗位 —— 岗位已购得;待其区块驻留后,在 SectGuardianSystem 的下一次心跳里,实体傀儡本身才会现身。 | sect()、actor()、postIndex()。 |
SectGuardianFellEvent | 否 | 一尊在世的护山傀儡倒下了。当致命一击始终没能归到某位玩家头上(环境伤害、阵法陷阱,或击杀者在判定前已消失)时,killerPlayerRef 为 null。 | sect()、postIndex()、killerPlayerRef()、consumed()。 |
SectGuardiansFallenEvent | 否 | 该宗大殿的最后一尊在世护山傀儡刚刚倒下(或化入永久消耗状态而消失),此刻已无一尊留存。纯属通知:无占据时长加成,也无惩罚。 | sect()。 |
声明为 @Nullable 的有:killerPlayerRef()。
讲道
plugin.siren.API.SermonEvents v0.10.2 —— 4 个事件(1 个可取消),涵盖修士在自己宗门的大殿开坛讲道、一位打坐中的听众首次合格的结算,以及讲道如何收场。开坛可以取消。面向玩家的文档:讲道。
此类混用 UUID 与 PlayerRef 两种标识;用 Universe.get().getPlayer(uuid) 解析 UUID,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreSermonStartEvent | 是 | 一名宗门成员即将开坛讲道。取消可回绝(对执行者而言,表现为开坛尝试直接失败)—— 在 SermonManager.start 中所有关卡都通过之后、贡献消耗被扣或冷却被盖戳之前触发,所以否决不让执行者损失任何东西。 | sect()、lecturer()、element()。 |
SermonStartEvent | 否 | 一名宗门成员在本宗大殿成功开坛讲道。 | sect()、lecturer()、element()、endsAtMillis()。 |
SermonListenerQualifiedEvent | 否 | 一名听众在本次讲道中的首次合格结算 —— 每个(讲道,听众)配对仅触发一次,即便经过降速或强制停止的转换,同一配对也不会再次触发。 | lecturerUuid()、listener()、element()、amountApplied()。 |
SermonEndEvent | 否 | 一场讲道结束了 —— 自然(时长耗尽)、提前(/cultivation sermon stop),或异常(讲者离开大殿区块/世界、大殿丢失、宗门被围攻、功能被禁用)。 | lecturerUuid()、sectName()、qualifiedListenerCount()、meritAwarded()、forfeited()。 |
功德
plugin.siren.API.MeritEvents v0.10.2 —— 3 个事件(1 个可取消),涵盖功德的获得与据此晋升品阶。获得可取消,也可重新衡量。面向玩家的文档:功德。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreMeritGainEvent | 是 | 功德即将因一桩善举而记入。取消则一文不付;用 setAmount 可重新衡量这桩善举。 | player()、deed()、amount() / setAmount(float)。 |
MeritGainEvent | 否 | 功德已实际记入 —— total / multiplier 是节流与上限施加之后的值。 | player()、deed()、amount()、total()、multiplier()。 |
MeritRankUpEvent | 否 | 该玩家的功德品阶变了 —— 每次跨越触发一次,去重方式与 DaoEvents.PathChangeEvent 相同。 | player()、from()、to()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
v0.11.1 deed() 是一个 MeritDeed,该枚举新增了一个常量 BREACH_CLEAR:在原版哥布林突袭、哥布林宝匣、虚空猎杀或地宫首领了结之时站在其近旁所得的功德(见突袭与首领之赏)。它可重复、没有受益人,所以既不受配对冷却约束,也不受 Merit-Min-Realm-Gap 约束;它受 Merit-Daily-Cap 限制,而对突袭与宝匣,还受 Breach-Reward-Daily-Cap 限制。两个功德事件都像对待其他善举一样携带它,所以针对 0.11.0 编译、对 MeritDeed 的 switch 表达式又没有 default 的扩展,在它出现时会于运行期抛出异常。
队伍
plugin.siren.API.PartyEvents v0.9.1 —— 5 个事件(1 个可取消),涵盖临时的、仅限当次会话的结伙:组建、加入、离开、解散与邀请。面向玩家的文档:队伍与秘境副本。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PrePartyInviteEvent | 是 | 一份邀请即将发出。取消可静默回绝(邀请者仍会收到管理器自己的结果)。 | inviterUuid()、targetUuid()。 |
PartyFormedEvent | 否 | 一位孤身队长的第一份邀请被接受 —— 队伍此刻成了一个群体,而不只是一位独自等待的队长。 | leaderUuid()、firstMemberUuid()。 |
PartyMemberJoinedEvent | 否 | 一位修士加入了已成型的队伍 —— 不是队伍的第一名成员,那一个是 PartyFormedEvent。 | leaderUuid()、memberUuid()。 |
PartyMemberLeftEvent | 否 | 一位修士离开了一支此后仍有成员的队伍。若离开的是队长,leaderUuid 就是新擢升的队长。 | leaderUuid()、memberUuid()。 |
PartyDisbandedEvent | 否 | 一支队伍不复存在 —— 或是队长径直解散,或是最后一名成员离开。formerMembers 是快照,而非实时视图。 | leaderUuid()、formerMembers()。 |
双修
plugin.siren.API.PartnerEvents v0.9.1 —— 3 个事件(1 个可取消),涵盖两位已结为道侣的修士同汲一条灵脉:结伴、解伴,以及结伴所授的灵气加成。除非安装了 Marriage 模组(CultivationAPI.isMarriageInstalled()),否则不起作用。面向玩家的文档:双修。
此类混用 UUID 与 PlayerRef 两种标识;用 Universe.get().getPlayer(uuid) 解析 UUID,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PartnerPairedEvent | 否 | 一位修士由未结伴转为结伴 —— 两位道侣在同一世界、彼此 Partner-Radius-Blocks 范围之内都坐下打坐。 | ref()、player()、partnerUuid()。 |
PartnerUnpairedEvent | 否 | 一位修士由结伴回到未结伴:道侣起身、离开半径、更换世界,或这一对以其他方式失效。formerPartnerUuid 是他原先的搭档。对先起身的那位道侣不触发 —— 只告知仍然坐着的一方。 | ref()、player()、formerPartnerUuid()。 |
PrePartnerQiBonusEvent | 是 | 一位结伴修士的打坐灵气加成即将生效。取消则本 tick 完全取消该加成(等同独坐);调整 setMultiplier 可重新缩放这一对搭档额外汲取多少灵气。 | ref()、player()、partnerUuid()、multiplier() / setMultiplier(float)。 |
声明为 @Nullable 的有:player()(所有携带它的事件);PrePartnerQiBonusEvent 上的 partnerUuid()。
拍卖行与行商
plugin.siren.API.MarketEvents v0.9.0 —— 12 个事件(3 个可取消),涵盖拍卖挂单的上架、购买、竞价、撤下与过期,以及云游行商 NPC 的开张与收摊。面向玩家的文档:拍卖行。
拍卖的变更都运行在 AuctionManager 的 synchronized 方法之内,因此这里的监听器正持有那把锁:读走你要的东西、交接出去、然后返回。切勿从监听器回调进 AuctionManager 的变更方法。这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreAuctionListEvent | 是 | 玩家即将挂出一件物品。取消可回绝(报告为被拦下)—— 此时卖家的背包尚未被动过。 | seller()、itemId()、quantity()、price() / setPrice(long)。 |
AuctionListingCreatedEvent | 否 | 一条挂单创建了,此刻已上架。 | seller()、listing()。 |
PreAuctionBuyEvent | 是 | 玩家即将买下一条挂单。取消可回绝 —— 此时尚无东西易手,挂单仍在架上。 | buyer()、listing()。 |
AuctionListingSoldEvent | 否 | 一条挂单售出了。listing 是已被移除的货架条目;sellerProceeds 是扣除坊市抽成之后记给卖家的数额。 | listing()、buyer()、sellerProceeds()。 |
AuctionListingCancelledEvent | 否 | 卖家撤下了自己仍在架上的挂单。 | listing()。 |
AuctionListingExpiredEvent | 否 | 一条未售出的挂单超过了 Market-Auction-Listing-Duration-Hours,已作为可领取的包裹退还卖家。 | listing()。 |
MerchantOpenedEvent | 否 | 云游行商在某个世界开张了。 | world()、x()、y()、z()。 |
MerchantClosedEvent | 否 | 云游行商的驻留结束,NPC 消失了。 | world()。 |
PreAuctionBidEvent | 是 | 玩家即将在限时拍卖上出价。取消可回绝 —— 此时尚无东西易手,前一位最高出价者也尚未被退款。刻意不设 setter:悄悄改动玩家刚刚承诺的数额会令人意外,所以重新调整一次出价的受支持做法就是取消它。 | bidder()、listing()、amount()。 |
AuctionBidPlacedEvent | 否 | 限时拍卖上有人出价,此刻成了在位的最高价。 | listing()、bidder()、amount()。 |
AuctionOutbidEvent | 否 | 在位的最高出价者被人超过,或其出价输给了提前一口价买断 —— 他们的灵石刚刚落入可领取的包裹(见 /market claim),即便人在离线。 | listing()、outbidBidder()、refundedAmount()。 |
AuctionClosedEvent | 否 | 一场至少有一次出价的限时拍卖结束 —— 最高出价者赢得物品,卖家在扣除坊市抽成之后获得 sellerProceeds。对限时拍卖路径而言,形状与 AuctionListingSoldEvent 一致;零出价的结束则改为触发现有的 AuctionListingExpiredEvent,保持不变。 | listing()、winner()、sellerProceeds()。 |
悬赏令
plugin.siren.API.BountyEvents v0.10.2 —— 4 个事件(2 个可取消),涵盖经 BountyManager.post 张贴一份委托、一次击杀即将计入某份 SLAY 委托,以及领取一份已完成的委托。面向玩家的文档:悬赏令。
悬赏榜自身轮换生成的委托不会触发 BountyPostedEvent —— 只有经 BountyManager.post 推上去的才会。这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
BountyPostedEvent | 否 | 一份委托被明确张贴到榜上 —— 它已在榜单之中并已持久化。bounty 是榜上的实时对象,不是副本。请读取它,不要改动。 | bounty()。 |
PreBountyClaimEvent | 是 | 一份已完成的委托即将发放。取消可径直回绝这次领取 —— 此时尚未发放任何东西,也尚未标记为已领取,所以这份接取只是停留在「已完成但未领取」,玩家可以再试。 | bountyId()、claimantUuid()。 |
PreBountyCreditEvent | 是 | 一次玩家击杀即将推进某份 SLAY 委托的进度。取消则整次接取一概跳过 —— 不记录任何进度,也不告知击杀者。这是悬赏榜与张贴诛令者双方共同遵从的唯一裁决:张贴者在此监听,套用它给自己的奖励所用的那些规则(配对冷却、赛季上限、沙盒与管理员绕过排除),并在自己的回答为否时取消。每个匹配的在世接取触发一次,在榜这边的所有关卡之后、任何进度被写入之前。 | bountyId()、killerUuid()、victimUuid()、bounty()。 |
BountyClaimedEvent | 否 | 一份委托被完整领取 —— 所许诺的每一项奖励都已到账,这份接取已标记为已领取。对 BountyManager.Result.PARTIAL 的领取永不触发,那种情形会让接取停在「已完成但未领取」以便重试。 | bountyId()、claimantUuid()、rewardQi()。 |
这里的每个事件都在引发它之物所在的世界线程上触发,且此时持有 BountyManager 自己的监视器。不要阻塞,也不要从监听器回调进 BountyManager 的变更方法(post、takeDown、retire、accept、claim、creditPlayerSlain、sweep):它们同步于同一个监视器,重入其中任何一个,都会在触发此事件的那个操作的半途中运行它。本模组确立的锁序是 SeasonManager,然后你的扩展,然后 BountyManager,所以这里的监听器已经持有了那条链上的最后一把锁 —— 在这些事件之内去碰扩展的监视器,等于倒着走,可能与另一条世界线程上正在开启的赛季死锁。请让监听器的主体不带任何锁。
斗法与较量
两位玩家出于自愿而彼此对抗、或并肩进行的一切。
斗法
plugin.siren.API.DuelEvents —— 8 个事件(3 个可取消),涵盖发起、接受,以及一场灵气赌斗如何结算。面向玩家的文档:斗法,以及指令页上的 /cultivation duel。
一场斗法经常比其中一名参与者的会话活得更久 —— 而那恰恰正是它作罢的缘由。这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
DuelEndReason:DEATH—— 一名斗者阵亡;押注易主;YIELD—— 一名斗者认输(/cultivation duel yield);押注易主,与 DEATH 完全一样 —— 这是胜者已知、结果已定的了结,绝不是「什么都没发生」;VOIDED—— 无法判定 —— 有参与者离开,或这场斗法超出了其最长时限。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreDuelChallengeEvent | 是 | 一份邀约即将发出。 | challenger()、challenged()、wager() / setWager(int) —— 事后仍会重新核对所配置的上限。 |
DuelChallengeEvent | 否 | 邀约正等待对方应答。 | challenger()、challenged()、wager()。 |
DuelDeclineEvent | 否 | 邀约已被拒绝;赌斗未开始。 | challenger()、challenged()。 |
PreDuelStartEvent | 是 | 一场赌斗即将开始。取消可回绝之 —— 无论如何邀约都已消耗,因此挑战者须重新发起一份。 | challenger()、challenged()、wager() / setWager(int) —— 在此重新调整的值,才是这场赌斗实际结算的数额。 |
DuelStartEvent | 否 | 赌斗已生效;双方均被标记为赌斗中。 | challenger()、challenged()、wager()。 |
DuelEndEvent | 否 | 赌斗结束。DEATH 与 YIELD 时胜者与败者是有意义的,且结算已排队;VOIDED 时二者不过是那两名参与者,什么也不易手。 | winner()、loser()、wager()、reason()、killer() —— DEATH 时指以自身伤害落下致命一击的玩家;若致命一击并非来自玩家(熔岩、坠落、阵法陷阱)或无法归因,则为 null;YIELD 与 VOIDED 时恒为 null。 |
PreDuelPayoutEvent | 是 | 一场已判定赌斗的押注即将转移。取消可让胜者一无所得。 | winner()、loser()、amount() / setAmount(int) —— 实际转移的量仍受败者所持数额的封顶。 |
DuelPayoutEvent | 否 | 押注已转移。amount 是败者所能拿出的数额,也正是胜者所得。 | winner()、loser()、amount()。 |
声明为 @Nullable 的有:killer()。
这些所覆写的配置键:setWager 对应 Duel-Max-Wager;相关键还有 Duel-Challenge-Expiry-Seconds、Duel-Max-Duration-Seconds、Duel-Overrides-World-Pvp 以及 Duels-Enabled 这道门禁。
大道赌斗
plugin.siren.API.DaoDuelEvents v0.10.1 —— 3 个事件(2 个可取消),涵盖叠在 DuelEvents 那种单纯灵气赌斗之上的灵石托管:挑战与结算可以取消,托管结清之后则报告结局。面向玩家的文档:斗法。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
DaoDuelEndReason:DEATH—— 一名斗者阵亡;灵石彩池已结清;YIELD—— 败者认输(/cultivation duel yield),而非被击杀;灵石彩池照样向他结清。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreDaoDuelChallengeEvent | 是 | 一份大道赌斗的挑战即将发出(灵气押注若有,完全由 DuelEvents.PreDuelChallengeEvent 处理 —— 这里只管灵石那一边)。取消可回绝;用 setSpiritStoneAmount 可重新调整押注(所配置的上限在其后重新核对)。 | challenger()、challenged()、spiritStoneAmount() / setSpiritStoneAmount(long)。 |
PreDaoDuelPayoutEvent | 是 | 一场已判定的大道赌斗的灵石彩池即将易手。取消则把败者的押注原封不动退还败者;setAmount 重新缩放败者被托管的押注中有多少被没收,以实际托管的数额封顶。无论哪种,胜者自己的押注都不受影响。 | winner()、loser()、amount() / setAmount(long)。 |
DaoDuelEndEvent | 否 | 一场已判定的大道赌斗的灵石彩池已结清 —— spiritStoneAmountPaid 是实际从败者托管中转给胜者的数额(外加任何能够收取的元素加成);胜者自己的押注总是另行退还给他,不计在这里。 | winner()、loser()、spiritStoneAmountPaid()、winnerElement()、loserElement()、winnerCountered()、reason()、decidedByOpponentDamage()。 |
声明为 @Nullable 的有:winnerElement();loserElement()。
赛事押注
plugin.siren.API.WagerEvents v0.10.2 —— 4 个事件(1 个可取消),涵盖观战者在大道赌斗大会的单场对局上押注灵石 —— 一个没有庄家账户的彩池式盘口。面向玩家的文档:斗法。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
WagerVoidReason:FORFEIT—— 一名斗者被判胜出,却并未真正打过一场(缺席/逾期弃权);DOUBLE_ELIMINATION—— 到期限时双方都不够资格,于是双双淘汰;VOIDED_DUEL—— 底层的斗法作废 —— 掉线,或超出Duel-Max-Duration-Seconds;YIELD—— 败者认输(/cultivation duel yield),而非被打败;NOT_OPPONENT_KILL—— 败者死了,却不是死于对手自己的伤害 —— 熔岩、坠落、溺水、阵法陷阱、第三方,或死亡路径根本无法归因的来源;TOO_FEW_BETTORS—— 对局确实分出了胜负,但某一方的不同押注者不足Wager-Min-Bettors-Per-Side人 —— 防串通规则;POOL_TOO_THIN—— 对局确实分出了胜负,但某一方的押注总额低于Wager-Min-Pool-Per-Side—— 让攻击者付出真实灵石的防串通规则;TOURNAMENT_RESET—— 此盘口存续期间,整届大会被重置、取消或重新开启;ACCOUNTING_FAILURE—— 守恒不变式的自检失败,于是不付一文,每一注原额退还。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreWagerPlacedEvent | 是 | 一位观战者即将为一注被扣费。所有已配置的关卡(功能启用、盘口开放、非斗者、非仍在参赛者、非同宗、单注/单届/单池限额)都已通过。取消可回绝这一注,不动灵石、不记任何东西。数额刻意不可设置。 | matchNumber()、bettor()、backed()、amount()。 |
WagerPlacedEvent | 否 | 一位观战者的灵石已被扣下,其押注已记录。backed 是他们所押注的斗者。 | matchNumber()、bettor()、backed()、amount()。 |
WagerMarketResolvedEvent | 否 | 一个盘口结算并派彩。payouts 把每位押注者映射到退回的灵石总额(本金加上其在败方彩池中的份额),stakes 映射到各自投入的数额,burned 是抽成加上不可整除的余数 —— 被销毁而非派发的灵石。在持有锦标赛管理器的监视器时触发;见下面的锁说明。 | matchNumber()、winner()、stakes()、payouts()、winnersPool()、losersPool()、burned()。 |
WagerMarketVoidedEvent | 否 | 一个盘口无人获彩,refunds 中的每一注都原额退还。reason() 说明缘由。在持有锦标赛管理器的监视器时触发;见下面的锁说明。 | matchNumber()、reason()、refunds()。 |
PreWagerPlacedEvent 与 WagerPlacedEvent 触发时,不持有本模组的任何监视器,运行在下注玩家自己的指令线程上。WagerMarketResolvedEvent 与 WagerMarketVoidedEvent 则在 DaoDuelTournamentManager 的监视器被持有时触发,位于其对局结算内部。对这两个事件的规矩是绝对的:不加锁、不跨管理器调用。不要加 synchronized,不要去碰另一条线程可能正持有的并发原语,也绝不要回调 DaoDuelTournamentManager、TournamentWagerManager、DaoDuelManager 或 DuelManager。把需要的东西从事件里抄出来,交给你自己的队列。重启时的退款什么都不触发 —— 它们运行在 Cultivation 的 setup() 之内,早于任何扩展登记监听器 —— 所以请改读可领取的包裹。
茶道
plugin.siren.API.TeaEvents v0.10.3 —— 4 个事件(1 个可取消),涵盖两人配合、考验反应时机的合奏(茶道):开始(可取消)、每一步的结算,以及茶会如何收场。面向玩家的文档:茶道。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此类中声明的枚举:
EndReason:COMPLETED—— 每条提示都已送出并评分 —— 正常收尾;LEFT—— 有参与者执行了/cultivation tea leave;DRIFTED—— 两位参与者相距超过Tea-Radius-Blocks的时间长过Tea-Grace-Seconds;DISCONNECTED—— 有参与者掉线;COMBAT—— 有参与者进入战斗(有一个生效的PunishWindowComponent);DISABLED—— 茶会进行到一半时,Tea-Enabled被关掉了。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreTeaCeremonyStartEvent | 是 | 一份待决邀约即将被接受,一场茶会即将开始(灵草尚未花费)。取消可回绝 —— 无论如何邀约都已消耗,所以发起者须再发一份新的。 | offerer()、accepter()、herbCost() / setHerbCost(int)。 |
TeaCeremonyStartEvent | 否 | 一场茶会真正开始了 —— 灵草已花费,会话已生效。 | sessionId()、playerA()、playerB()。 |
TeaStepResolvedEvent | 否 | 一条提示(单个 BOIL/STEEP/POUR/SERVE 步骤)被评分了。 | sessionId()、round()、step()、playerACorrect()、playerBCorrect()、scoreDelta()。 |
TeaCeremonyEndEvent | 否 | 一场茶会以某种方式结束了 —— 只有 reason 为 EndReason.COMPLETED 时,harmony / band 才有意义;所有作废的缘由都报告 harmony=0f / band=DISCORDANT 与 rewarded=false,因为异常结束绝不发放奖励(灵草无论如何都已花掉 —— 此事件不涉及这一点,它在茶会开始时无条件施加)。 | sessionId()、playerA()、playerB()、reason()、harmony()、band()、rewarded()。 |
围棋
plugin.siren.API.WeiqiEvents v0.10.3 —— 7 个事件(2 个可取消),涵盖围棋(Go):邀请与拒绝、对局开始、每一手,以及一局如何结算。邀请与开局可以取消。面向玩家的文档:围棋。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreWeiqiInviteEvent | 是 | 一份邀请即将发出。取消可径直回绝(例如扩展所执行的冷却或黑名单)。 | inviter()、invitee()。 |
WeiqiInviteEvent | 否 | 一份邀请已发出,正等待对方应答。 | inviter()、invitee()。 |
WeiqiDeclineEvent | 否 | 一份邀请被拒绝;没有开局。 | inviter()、invitee()。 |
PreWeiqiMatchStartEvent | 是 | 一局棋即将开始(接受方刚刚接受了一份待决邀请)。取消可回绝 —— 无论如何邀请都已消耗,所以邀请者须再发一份新的。 | blackUuid()、whiteUuid()、boardSize()、komi() / setKomi(float)。 |
WeiqiMatchStartEvent | 否 | 一局棋已然开始。blackUuid 恒为接受方(先手,对受邀者的一份礼让);whiteUuid 是最初的邀请者。 | matchId()、blackUuid()、whiteUuid()、boardSize()、komi()。 |
WeiqiMoveEvent | 否 | 一手棋结算 —— 要么在 index 处落下一子(平铺的 y * boardSize + x 棋盘索引,可经 WeiqiBoard.xOf / yOf 解码),要么虚着,二者不会同时发生。 | matchId()、player()、color()、index()、pass()、capturedCount()。 |
WeiqiMatchEndEvent | 否 | 一局棋结束。对 WeiqiMatch.Outcome.ABANDONED / WeiqiMatch.Outcome.TIMED_OUT,winner 为 null(未分胜负的对局无人获胜);对 WeiqiMatch.Outcome.TWO_PASS / WeiqiMatch.Outcome.RESIGNED 则恒有值。 | matchId()、blackUuid()、whiteUuid()、winner()、outcome()、blackScore()、whiteScore()、totalMoves()。 |
声明为 @Nullable 的有:winner()。
世界
阵法与洞府,天穹,全服范围的遭遇,你前往的去处,以及你在那里的所获。
阵法
plugin.siren.API.FormationEvents —— 8 个事件(4 个可取消),涵盖锚定于区块的灵阵之布设与驱散、以祭坛为锚的阵法变更阶位,以及困仙阵伤及入侵者。面向玩家的文档:阵法。
此类混用 UUID 与 PlayerRef 两种标识;用 Universe.get().getPlayer(uuid) 解析 UUID,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreFormationPlaceEvent | 是 | 一座阵法即将布下。取消后它会报告此地已被设防。 | owner()、sectName()(阵法归其个人时为空)、world()、chunkX()、chunkZ()、type()、radiusChunks() / setRadiusChunks(int)。 |
FormationPlaceEvent | 否 | 阵法已在其区块上生效。 | owner()、sectName()、formation()。 |
PreFormationRemoveEvent | 是 | 一座阵法即将被其掌阵者驱散。取消可让它继续矗立。 | owner()、sectName()、formation()。 |
FormationRemoveEvent | 否 | 已驱散。formation 是那个已被移除的对象。 | owner()、sectName()、formation()。 |
PreFormationTrapStrikeEvent | 是 | 困仙阵即将伤及一名入侵者。取消可让他完全逃过这一次结算 —— 无粒子、无减益、无伤害。把伤害设为 0 则只定住他而不伤其身。 | ref()、player()、world()、chunkX()、chunkZ()、damage() / setDamage(float) —— 在致死上限之后、护甲之前;入侵者的生命值无法解析时为 0。 |
FormationTrapStrikeEvent | 否 | 入侵者已受伤。 | ref()、player()、world()、chunkX()、chunkZ()、damage()。 |
PreFormationTierChangeEvent | 是 | 一座以祭坛为锚的阵法的阶位即将变更。取消可彻底回绝这次变更;用 setToTier 可压低(但不能完全阻止)一次上升。 | formation()、fromTier()、toTier() / setToTier(int)。 |
FormationTierChangeEvent | 否 | 一座以祭坛为锚的阵法的阶位刚刚变了。纯属通知 —— 此事件触发时,新阶位已经在 formation 上生效。 | formation()、fromTier()、toTier()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
这些所覆写的配置键:setRadiusChunks 视 type() 而定,对应 QiGathering-Radius-Chunks、Warding-Radius-Chunks 或 Trapping-Radius-Chunks;PreFormationTrapStrikeEvent.setDamage 对应 Trapping-Damage-Percent-Of-Max-Health(与之并列的还有 Trapping-Lethal、Trapping-Interval-Seconds 与 Trapping-Debuff-Duration-Seconds)。整套系统的门禁:Formations-Enabled 与 Max-Formations-Per-Controller。
洞府
plugin.siren.API.DwellingEvents —— 12 个事件(6 个可取消),涵盖洞府的开辟、其灵泉、供奉与闭关。面向玩家的文档:洞府。
宗门山门灵泉是自动创建并随其宗门大殿迁移的;那套内务处理刻意不触发任何事件。请改为监听宗门大殿的设立与夺取事件 —— 它们才是其成因。此类混用 UUID 与 PlayerRef 两种标识;用 Universe.get().getPlayer(uuid) 解析 UUID,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreDwellingClaimEvent | 是 | 一座洞府即将开辟或迁移。取消后它会报告此地已被设防。 | owner()、world()、chunkX()、chunkZ()、veinTier()、moved()、radiusChunks() / setRadiusChunks(int)。 |
DwellingClaimEvent | 否 | 洞府已开辟,或已有的一座完成迁移 —— 迁移会保留所蓄灵泉与已付供奉。 | owner()、dwelling()、moved()。 |
PreDwellingAbandonEvent | 是 | 一座洞府即将被舍弃。取消可保其不失。 | owner()、dwelling()。 |
DwellingAbandonEvent | 否 | 已舍弃;灵泉中所存也随之而去。 | owner()、dwelling()。 |
PreDwellingLapseEvent | 是 | 一座洞府即将因未付供奉而被收回。取消可为其缓刑 —— 它只能撑到下一次扫描重新检验它为止,因此请从一个「持续在做判断」的监听器中取消,而非一次性的。 | dwelling()。 |
DwellingLapseEvent | 否 | 一处私人洞府在其宽限期过后被世界收回。 | dwelling()。 |
PreSpringCollectEvent | 是 | 一眼灵泉即将被饮尽。取消可让它保持满盈。 | dwelling()、amount() / setAmount(float) —— 改变取用者带走的量;灵泉无论如何都会被清空。 |
SpringCollectEvent | 否 | 灵泉已被清空。amount 是交付出去的灵气 —— 由调用方为其入账。 | dwelling()、amount()。 |
PreUpkeepDepositEvent | 是 | 供奉即将付讫。取消后它会报告未蓄存任何东西。 | dwelling()、itemId()、quantity()、hours() / setHours(float) —— 整份献纳所值几何,在蓄存时长封顶之前。 |
UpkeepDepositEvent | 否 | 供奉已缴入。hoursGranted 是实际蓄存下来的量,一旦触顶便少于所献纳的量。 | dwelling()、itemId()、quantity()、hoursGranted()。 |
PreSeclusionSettleEvent | 是 | 一次闭关即将结算。取消可使其作废 —— 玩家会被告知灵泉已干涸。 | ref()、player()、dwelling()、hours()(已被 Seclusion-Max-Hours 封顶)、qi() / setQi(float)(当 Seclusion-Drains-Spring 为开时,已被限制在灵泉所能覆盖的范围内)。 |
SeclusionSettleEvent | 否 | 修士已出关,并已为其离开的时日付讫。 | ref()、player()、dwelling()、hours()、qi()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
这些所覆写的配置键:PreDwellingClaimEvent.setRadiusChunks 对应 Dwelling-Radius-Chunks;PreSpringCollectEvent.setAmount 对应 Spring-Qi-Per-Hour、Spring-Pool-Base-Cap 与 Spring-Pool-Cap-Per-Realm;PreUpkeepDepositEvent.setHours 对应 Upkeep-Item-Hours,并受 Upkeep-Max-Banked-Hours 封顶;PreDwellingLapseEvent 对应 Upkeep-Grace-Hours;PreSeclusionSettleEvent.setQi 对应 Seclusion-Qi-Per-Hour。整套系统的门禁:Dwellings-Enabled、Upkeep-Enabled、Seclusion-Enabled。
引脉阵
plugin.siren.API.VeinTapEvents v0.11.1 —— 7 个事件(2 个可取消),涵盖修士布在丰沛灵脉或龙脉上的阵法:布阵、阵主从中领取、对手劫掠,以及释放。面向玩家的文档:引脉阵。
玩家以 UUID 标识。监听器在引发该事件的线程上运行(布阵或劫掠玩家的世界线程,或某条指令线程),此时不持有阵法管理器的任何锁,所以请保持轻量,且不要在监听器里写入 Store。
此类中声明的枚举:
Reason(阵法为何不再矗立):RELEASED—— 阵主,或宗门的宗主或长老,将其释放;UPROOTED—— 阵法所在地界的主人将其拔除;SECT_DISBANDED—— 阵主宗门被解散;ADMIN—— 管理员以/cultivation admin tap clear将其移除;EXPIRED—— 管理员的测试阵法到了时限。Outcome(劫掠如何结束):SIPHONED—— 抽取守住了:劫掠者取走了他的份额,阵法随即休眠;BROKEN—— 劫掠者离开灵脉、死亡、断线,或阵法不复存在。什么都没被取走。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreVeinTapAnchorEvent | 是 | 每道关卡(功能开启、境界、灵脉、地面、间隔、数量上限)都已通过,但尚未消耗或写入任何东西。取消则布阵以一句笼统的“有什么东西阻止了”失败;阵旗不会被消耗。 | placer()、sectName()(个人阵法为空)、world()、chunkX()、chunkZ()、tier()(1 丰沛,2 龙脉)。 |
PreVeinTapRaidEvent | 是 | 一场劫掠已通过每道关卡,但引导尚未开始,也尚未警告任何阵主。取消则劫掠以一句笼统的“有什么东西阻止了这次劫掠”失败。 | raider()、tapId()、controllerSect()、controllerOwner()。 |
VeinTapAnchoredEvent | 否 | 一座阵法已布下。 | placer、tapId、sectName、world、chunkX、chunkZ、tier。 |
VeinTapCollectedEvent | 否 | 阵主从阵法领取了产出。分文未得的领取不触发。 | collector、tapId、stones(进入行囊的)、qi(计入倍率后入账的)。 |
VeinTapRaidStartedEvent | 否 | 一场劫掠的引导开始。 | raider、tapId、requiredSeconds。 |
VeinTapRaidEndedEvent | 否 | 一场劫掠结束。 | raider、tapId、outcome、stones、qi(SIPHONED 时所取的份额;若行囊已满,灵石仍可能被保管)。 |
VeinTapReleasedEvent | 否 | 一座阵法不再矗立。 | actor(解散、到期或管理员所致时为 null)、tapId、sectName、ownerUuid、world、chunkX、chunkZ、reason。 |
声明为 @Nullable 的有:actor()。
这些事件没有可重新调整的配置键,只能否决或观察。开关:Vein-Tap-Enabled、Vein-Tap-Raid-Enabled。
天象
plugin.siren.API.CelestialEvents v0.8.0 —— 3 个事件(1 个可取消),涵盖全服共享的天穹。两个钩子对每种天象类型都是通用的,而不是每种异象各设一对,所以要对某一种作出反应,请按 type().id() 分支。面向玩家的文档:天象。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreCelestialEventStartEvent | 是 | 一场异象即将开始,无论出自调度还是 /celestial start。取消即否决它 —— 调度器只会重新排期,而不会换一场别的。setDurationMinutes 可让它比其类型的默认时长更长或更短。 | type()、durationMinutes() / setDurationMinutes(float)、forcedByAdmin()。 |
CelestialEventStartEvent | 否 | 它已开始。除身处天劫风暴者外,所有玩家的天穹都已在切换。 | type()、startedAtMillis()、endsAtMillis()、forcedByAdmin()。 |
CelestialEventEndEvent | 否 | 它已结束,无论出自计时还是 /celestial stop。 | type()、startedAtMillis()、endedAtMillis()、forcedByAdmin()。 |
注册属于自己的异象类型是另一个调用 —— 见注册表。这些事件携带的是 CelestialEventType,因此监听者眼中扩展模组贡献的异象,与内置异象完全平起平坐。CelestialManager 自己注册四种 —— spirit_tide、meteor_shower、blood_moon 与 starfall_convergence —— 另有三种由拥有它们的子系统注册:heavenly_schism(正魔之战)、beast_tide(兽潮)与 beast_omen(灾劫兽)。后两种以零权重注册,调度器永不会抽到它们;由各自的管理器开启它们,并在这些事件之旁触发各自的事件。
兽潮
plugin.siren.API.TideEvents v0.9.0 —— 6 个事件(3 个可取消),涵盖对宗门大殿或洞府的一场围攻(兽潮):预警阶段、每一波,以及结算。它们与该兽潮自己那个天象类型的 CelestialEvents 并行触发,而非取而代之。面向玩家的文档:兽潮。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreTideStartEvent | 是 | 已选定目标,兽潮即将进入预警(WARNING)阶段。取消则整个放弃这次选取 —— 调度器只是等待下一次检查。 | worldName()、abode()、targetName()、waveCount() / setWaveCount(int)。 |
TideStartEvent | 否 | 兽潮的预警阶段开始了 —— 目标已锁定,信标即将生成。 | assaultId()、worldName()、abode()、targetName()、waveCount()。 |
PreTideWaveEvent | 是 | 一波兽群即将触发。取消只跳过这一次尝试(计时器与波次序号照常推进 —— 守方得到的是喘息,而不是多出来的一波)。 | assaultId()、waveIndex()。 |
TideWaveEvent | 否 | 一波兽群刚刚触发(或曾尝试触发 —— 见 PreTideWaveEvent)。 | assaultId()、waveIndex()、waveCount()。 |
PreTideResolveEvent | 是 | 围攻即将结算。取消则跳过发放奖励(WON)或压制/冷却(LOST)—— 围攻无论如何都会结束并清理,被跳过的只是与结局相关的那项副作用。setSuppressionSteps / setSuppressionDurationMinutes 可重新调整败局;setContributionReward 重新调整胜局。 | assaultId()、result()、suppressionSteps() / setSuppressionSteps(int)、suppressionDurationMinutes() / setSuppressionDurationMinutes(float)、contributionReward() / setContributionReward(int)。 |
TideResolveEvent | 否 | 围攻结束了 —— 结局(以及任何奖励/压制)都已施加。 | assaultId()、worldName()、abode()、targetName()、result()。 |
灾劫兽
plugin.siren.API.WorldBossEvents v0.9.1 —— 4 个事件(1 个可取消),涵盖一头游荡的、孑然独行而无固定目标的世界首领(灾劫兽):凶兆阶段开始、首领真正现身,以及遭遇结算。只有开始可以取消。面向玩家的文档:灾劫兽。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreWorldBossStartEvent | 是 | 一头灾劫兽即将开始它的凶兆阶段。取消则整个放弃这次开始 —— 调度器只是等待下一次检查。它不携带可重新调整的数值。 | worldName()、roleId()、position()。 |
WorldBossStartEvent | 否 | 一头灾劫兽的凶兆(OMEN)阶段开始了 —— 它的出生点与物种已锁定,凶兆天空与公告已然生效。 | encounterId()、worldName()、roleId()、position()。 |
WorldBossSpawnEvent | 否 | 凶兆结束,首领 NPC 此刻真正存在于世间(进入 ACTIVE 活跃阶段)。 | encounterId()、worldName()、roleId()、position()、bossRef()。 |
WorldBossResolveEvent | 否 | 遭遇结束了,无论因何缘故 —— 任何奖励发放都已排入队列。 | encounterId()、worldName()、roleId()、result()、contributorCount()、totalContribution()。 |
虚空裂隙
plugin.siren.API.RiftEvents v0.10.0 —— 5 个事件(1 个可取消),涵盖一场随机触发的全服世界事件:裂隙开启,掷出固定数目的波次,召出一头首领级的守护者,随后以 SEALED 或 COLLAPSED 收场。v0.11.1 默认的波次如今是随第 7 版本而来的虚空阵营(Void Larva、Void Crawler、Voidtaken Goblin、Void Eye 与 Void Spawn),不再是堕化的兽群;事件本身没有变化。只有开启可以取消。面向玩家的文档:虚空裂隙。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreRiftOpenEvent | 是 | 一道虚空裂隙即将开始它的开启阶段。取消则整个放弃这次开启 —— 调度器只是等待下一次检查。它不携带可重新调整的数值。 | worldName()、position()。 |
RiftOpenEvent | 否 | 一道虚空裂隙的开启(OPENING)阶段开始了 —— 它的锚点与出生点已锁定,世界事件标记与公告已然生效。 | riftId()、worldName()、position()。 |
RiftWaveEvent | 否 | 突袭(ASSAULT)阶段中刚刚掷出了一波。waveIndex 从 0 起数;waveCount 是这道裂隙的总波数。 | riftId()、worldName()、position()、waveIndex()、waveCount()、spawnConfigId() —— 这一波所用的刷怪器资产,即 Rift-Wave-Spawn-Config-Ids 中的一项。v0.11.1 默认是 Cultivation_VoidRift_Surge_Fodder、Cultivation_VoidRift_Surge_Bruiser 或 Cultivation_VoidRift_Surge_Elite,此前是 Cultivation_VoidRift_Fodder、Cultivation_VoidRift_Bruiser 或 Cultivation_VoidRift_Elite;保存的列表若仍与旧默认值相同,加载时会自动升级,自定义过的列表则原样保留。 |
RiftWardenSpawnEvent | 否 | 突袭阶段结束,守护者 NPC 此刻真正存在于世间(进入 WARDEN 守护阶段)。 | riftId()、worldName()、roleId()、position()、wardenRef()。 |
RiftResolveEvent | 否 | 遭遇结束了,无论因何缘故 —— 任何奖励发放都已排入队列。outcome 恒为 RiftPhase.SEALED 或 RiftPhase.COLLAPSED。 | riftId()、worldName()、position()、outcome()、contributorCount()、totalContribution()。 |
散修客
plugin.siren.API.RogueEvents v0.10.2 —— 3 个事件(1 个可取消),涵盖一名散修客 NPC 的刷出与被击杀。刷出可以取消。面向玩家的文档:散修客。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreRogueCultivatorSpawnEvent | 是 | 一名散修客即将在 worldName 的 anchorPosition 附近刷出。取消可彻底回绝这次刷出 —— 该世界的下次刷出计时照常推进,与一次因找不到合适地面而被拒的判定无异。 | worldName()、anchorPosition()、anchorPlayerUuid()、realmOrdinal() / setRealmOrdinal(int)、daoElementName() / setDaoElementName(String)。 |
RogueCultivatorSpawnedEvent | 否 | 一名散修客刷出完毕,已在世间打上标记并生效。 | encounterId()、npcRef()、worldName()、realmOrdinal()、daoElementName()。 |
RogueCultivatorSlainEvent | 否 | 一名散修客被击杀了 —— 此事件触发时,任何秘籍/灵核/遗泽的掷骰都已结算。 | encounterId()、killerUuid()、worldName()、manualAwarded()、bonusCoreAwarded()、testamentAwarded()。 |
声明为 @Nullable 的有:killerUuid()。
游历道友
plugin.siren.API.RivalEvents v0.9.1 —— 2 个事件(1 个可取消),涵盖向一名游历道友 NPC 发起挑战,以及击败它的奖励。面向玩家的文档:游历道友。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreRivalChallengeEvent | 是 | 玩家右键点击,向一名游历道友发起挑战。取消可彻底回绝这次挑战 —— 对手仍保持 ROAMING,这次交互不起作用,与 DuelEvents.PreDuelChallengeEvent 给予斗法挑战的「沉默也是一种有效回答」形态相同。 | encounterId()、challengerUuid()、npcRef()。 |
RivalDefeatedEvent | 否 | 一名被挑战的游历道友已被击败 —— 胜者的奖励已经发放。 | encounterId()、winnerUuid()、worldName()、qiAwarded()、manualAwarded()、materialAwarded()。 |
秘境
plugin.siren.API.SecretRealmEvents v0.9.0 —— 2 个事件(均不可取消),涵盖一处洞天的结界落下(可进入)或重新升起(封闭)。只设后置事件:开启与封闭是调度器的确定性结果,而不是下游有可能真正否决的请求。面向玩家的文档:秘境。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
SecretRealmOpenEvent | 否 | 一处秘境开启了 —— 结界已然落下,可以进入。 | siteId()、tier()、world()、chunkX()、chunkZ()、source()、sectName()、closesAtMillis()。 |
SecretRealmCloseEvent | 否 | 一处秘境封闭了。forced 仅在管理员立即强制关闭时为 true(SecretRealmManager.forceClose);秘境在时长/宽限期满后自然关闭则为 false。 | siteId()、tier()、world()、chunkX()、chunkZ()、forced()。 |
秘境深渊
plugin.siren.API.DepthsEvents v0.9.1 —— 4 个事件(均不可取消),涵盖一场单人的深渊探索:开始、一层通关(附带它刚掷出的托管奖励)、撤出真正发放奖励,以及探索因任何缘故结束。只设后置事件,缘由同 SecretRealmEvents。面向玩家的文档:深渊。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
DepthsRunStartEvent | 否 | 一场单人深渊探索开始了,第 1 层即将刷出。 | runId()、ownerUuid()、siteId()、world()。 |
DepthsFloorClearEvent | 否 | 一层的灵兽尽数毙命 —— escrowSize 是计入本层这次掷骰之后,这趟探索尚未入账的托管总数(比此前多 0 或 1,因为掷骰可能落空)。 | runId()、ownerUuid()、floor()、escrowSize()。 |
DepthsExtractEvent | 否 | 这趟探索的托管奖励刚刚真正发放 —— 仅当 rewardsGranted 大于零时才触发,无论玩家选择了撤出,还是探索自动撤出(登出/秘境关闭)。 | runId()、ownerUuid()、depthReached()、rewardsGranted()。 |
DepthsRunEndEvent | 否 | 探索结束了,无论因何缘故 —— 只触发一次,位于同一结局所产生的任何 DepthsExtractEvent 之后。 | runId()、ownerUuid()、reason()、depthReached()。 |
试炼塔
plugin.siren.API.PagodaEvents v0.10.2 —— 3 个事件(1 个可取消),涵盖一层通关、一趟攀登结束,以及通关奖励 —— 后者可以取消,也可重新缩放。面向玩家的文档:试炼塔。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
此处有一个枚举:PagodaRunEndReason(DIED、LEFT、TIMED_OUT、DISCONNECTED)。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PrePagodaRewardEvent | 是 | 一层通关奖励即将发放。取消则什么也不发;调用方无论如何都会推进这趟攀登与记录。 | playerUuid()、floor()、spiritStoneAmount() / setSpiritStoneAmount(long)、qiAmount() / setQiAmount(float)。 |
PagodaFloorClearedEvent | 否 | 试炼塔的一层通关了 —— 仅在首次通关(最高层记录真正推进)时 newRecord 为 true,重玩时为 false。 | playerUuid()、floor()、newRecord()。 |
PagodaRunEndedEvent | 否 | 一趟试炼塔攀登结束了,无论因何缘故。floorReached 是攀登结束时所在的那一层,不一定是已通关的一层 —— 层中死亡永不推进玩家自己的记录。 | playerUuid()、floorReached()、reason()。 |
宝藏与遗迹
plugin.siren.API.TreasureEvents v0.9.1 —— 2 个事件(1 个可取消),涵盖领取一处埋藏宝藏或进入一座遗迹宝库 —— 一对事件同时涵盖两个品阶,因为二者领取的是同一类地点。面向玩家的文档:寻宝与遗迹探索。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreTreasureClaimEvent | 是 | 玩家即将领取一处埋藏宝藏或进入一座遗迹宝库。取消可彻底回绝 —— 该处仍未被领取,指令不起作用,与 RivalEvents.PreRivalChallengeEvent 给予游历道友挑战的「沉默也是一种有效回答」形态相同。 | siteId()、tier()、playerUuid()。 |
TreasureClaimedEvent | 否 | 一处宝藏被领取/进入了 —— 奖励已经发放。 | siteId()、tier()、playerUuid()、worldName()、qiAwarded()、manualAwarded()、materialAwarded()。 |
传送阵
plugin.siren.API.ArrayEvents v0.10.3 —— 2 个事件(1 个可取消),涵盖经传送阵网络在洞府、宗门大殿、秘境之地、识海或天界之间往来。这趟行程可以取消,也可重新定价。面向玩家的文档:传送阵。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreArrayTravelEvent | 是 | 一位修士即将经传送阵出行。取消可回绝这趟行程(不扣任何东西,也不移动);用 setQiCost 可重新定价。该费用在此事件触发之后才扣,并对照旅者存蓄的灵气重新核对。 | ref()、player()、destinationKind()、destinationId()、qiCost() / setQiCost(float)。 |
ArrayTravelEvent | 否 | 一位修士成功经传送阵出行。qiCost 是实际扣下的最终数额(管理员绕过时为 0)。 | ref()、player()、destinationKind()、destinationId()、qiCost()。 |
声明为 @Nullable 的有:ref()(所有携带它的事件);player()(所有携带它的事件)。
任务、赛季与宝阁
剧情,共享的赛季时钟,以及从网络商店送达的购买。
云游任务
plugin.siren.API.QuestEvents v0.9.1 —— 5 个事件(1 个可取消),涵盖从云游 NPC 发布者手中接下一条任务链、逐步推进、完成并足额领到奖励,或将其放弃。只有接取可以取消。面向玩家的文档:游历任务。
PreQuestAcceptEvent 是唯一可以否决的决定(扩展有正当理由不让某位玩家接某条任务链);其余事件所报告的,是一台早已在运转的状态机的下一个状态。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreQuestAcceptEvent | 是 | 玩家即将接下一条任务链。所有内置的拒绝条件(境界门槛、每账号一次、冷却、任务链上限)都已通过;取消则无论如何都回绝。监听器取消时不写入任何东西。 | ref()、player()、chainId()、giverRoleId()。 |
QuestAcceptEvent | 否 | 玩家接下了一条任务链 —— 进度行已写入,对于地点型任务链,其地点也已掷出。 | ref()、player()、chainId()、giverRoleId()。 |
QuestStepAdvanceEvent | 否 | 一条任务链的一步刚刚完成。 | ref()、player()、chainId()、completedStepIndex()、nextStepIndex()、finalStep()。 |
QuestCompleteEvent | 否 | 一条任务链已完全结束,并且已完全付酬 —— 每一项奖励都已到账。每趟只触发一次,即这趟进度转为 COMPLETED 的那一刻。 | ref()、player()、chainId()、completionCount()。 |
QuestAbandonEvent | 否 | 玩家放弃了一趟进行中的任务。正等候发放奖励的那一趟永不触发 —— 那样的无法放弃。 | ref()、player()、chainId()、stepIndex()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
主线
plugin.siren.API.CampaignEvents v0.9.1 —— 3 个事件(1 个可取消),涵盖任务系统中的章节推进(包括一条主线的第一章)与主线完结。只有推进可以取消。面向玩家的文档:游历任务。
PreCampaignChapterAdvanceEvent 是唯一可以否决的决定。它也会在一条主线的第一章触发,此时 fromChapterIndex() 为 -1,所以扩展可以像回绝任何后续推进那样,回绝一条主线的开启。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
PreCampaignChapterAdvanceEvent | 是 | 玩家即将进入新的一章(当 fromChapterIndex 为 -1 时,则是开启主线的第一章)。所有内置的拒绝条件(境界门槛、已在进行/已完成)都已通过;取消则无论如何都回绝。 | ref()、player()、campaignId()、fromChapterIndex()、toChapterIndex()。 |
CampaignChapterAdvanceEvent | 否 | 一章刚刚成为玩家的当前章 —— 或是主线的第一章(经 CampaignManager.start),或是接在已完结的一章之后推进而来。newChapterIndex 可能仍被它自己的境界门槛锁着;若监听器在乎这一点,请查看 CampaignManager.getProgress。 | ref()、player()、campaignId()、previousChapterIndex()、newChapterIndex()。 |
CampaignCompleteEvent | 否 | 一条主线的所有章节都已完结。每趟只触发一次,即最后一章的任务链完成的那一刻。 | ref()、player()、campaignId()。 |
声明为 @Nullable 的有:player()(所有携带它的事件)。
赛季
plugin.siren.API.SeasonEvents v0.10.2 —— 2 个事件(均不可取消),涵盖共享的赛季节律开启与结束一个赛季。只设后置事件。面向玩家的文档:赛季循环与英名阁。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
SeasonOpenEvent | 否 | 一个新赛季开启了,其开始时间戳已持久化。seasonId 是此刻在跑的赛季(即将结束那个赛季的 id 加一,全新安装时为 1)。在赛季更替时,它紧接在上一赛季的 SeasonCloseEvent 之后触发;全新安装,或 Season-Enabled 被开启后的第一个 tick,则单独触发。 | seasonId()、startedAtMillis()。 |
SeasonCloseEvent | 否 | 一个赛季结束了:它的英名阁条目与冠军名单已写入,排行榜基线即将在下一次开启时作废。seasonId 是刚刚结束的那个赛季。在正魔之战的赛季总计被重置之前触发,所以监听器看到的仍是完整的收官赛季总计。 | seasonId()、closedAtMillis()。 |
一台在赛季边界上离线的服务器,会在 Cultivation 自己的 setup() 期间结束并重开该赛季,而那早于任何扩展的 setup()。这次开启到不了任何扩展监听器,因为监听器列表此时仍是空的。一个必须知道当前是哪个赛季的扩展,得在自己的 setup() 或首个 tick 里去问 CultivationAPI.getCurrentSeasonId(),并把这些事件纯粹当作「我在旁观时它变了」。
两者都在最先走到赛季泵的那条世界线程上触发 —— 全服范围,而非某位玩家的世界 —— 且此时持有 SeasonManager 自己的监视器。不要阻塞,并在触碰任何人的组件之前,先按玩家切换线程(CompletableFuture.runAsync(task, theirWorld))。这两个事件是悬赏令一节所述那条锁链的链首。
宝阁权益
plugin.siren.API.StoreBenefitEvents v0.8.0 —— 3 个事件(均不可取消),涵盖宝阁同步。三者皆不可取消:权益名单是关于一笔购买的事实,而不是服务器有权表决的决定。
这里的玩家以 UUID 而非 PlayerRef 标识;用 Universe.get().getPlayer(uuid) 解析,并检查 isValid()。
| 事件 | 可取消 | 触发时机 | 暴露 |
|---|---|---|---|
BenefitGrantedEvent | 否 | 本次运行中首次发现某玩家对某项权益有权。 | playerUuid()、benefit()。 |
BenefitRevokedEvent | 否 | 某玩家不再出现在名单上 —— 退款,或该权益在本服被禁用。 | playerUuid()、benefit()。 |
SyncCompletedEvent | 否 | 一轮完整同步结束,无论出自周期还是 /cultivation store recheck 强制触发。 | products()、granted()、revoked()、failedProducts()。 |
failedProducts() 正是监听者用来分辨「无人拥有它」与「我们联系不上服务器」的依据 —— 同步是失败即放行的,因此端点不可达会让所有人保持原状,而不是把权益撤销。
与玩法事件不同,这些事件触发在远程检查线程上,而不是世界线程:授予与撤销是由一次 HTTP 扫描发现的,手边并没有世界。需要触碰玩家的监听器,必须用 Universe.get().getPlayer(uuid) 找到他们,检查 isValid(),并在读写任何组件之前先切到他们的世界线程。