开发接口
LyGalaxyDecomposition 提供公共接口 LyDecompositionAPI。外部插件可以读取规则、判断分解条件、预览产物、执行分解、创建物品库物品、替换 PlaceholderAPI 变量、执行命令、打开分解界面、读取外部适配器状态,以及重新加载插件配置。
接口完整类名:
java
Ly.galaxy.decomposition.client.plugin.api.LyDecompositionAPIAPI 实例可通过插件入口类获取:
java
import Ly.galaxy.decomposition.client.license.Start;
import Ly.galaxy.decomposition.client.plugin.api.LyDecompositionAPI;
// decompositionApi 保存 LyGalaxyDecomposition 当前提供的公共接口。
LyDecompositionAPI decompositionApi = Start.getAPI();调用分解、界面或命令相关方法前,应先确认 API 实例不为 null,并通过 isReady() 判断插件是否至少成功加载过一次配置。首次加载失败、插件尚未完成初始化或 API 已关闭时,isReady() 返回 false。
接入要求
外部插件需要将 LyGalaxyDecomposition 加入编译依赖,并在自身的 plugin.yml 中声明依赖关系。
需要强制等待 LyGalaxyDecomposition 加载时使用 depend:
yaml
depend:
- LyGalaxyDecomposition仅在 LyGalaxyDecomposition 存在时启用相关功能时使用 softdepend:
yaml
softdepend:
- LyGalaxyDecomposition公共接口使用 Bukkit 的 Player、ItemStack 和事件系统。调用方不应将 LyGalaxyDecomposition 的实现类打包进自己的插件,只将插件本体作为编译依赖。
线程与状态要求
| 方法 | 主线程要求 | API 未就绪时的行为 |
|---|---|---|
isReady() | 无强制检查 | 返回 false |
getRules() | 无强制检查 | 返回当前规则快照;首次加载前通常为空 |
getGlobalConditions() | 无强制检查 | 返回当前全局条件快照 |
getRule(...) | 无强制检查 | 按当前规则仓库查询 |
match(...) | 无强制检查 | 方法本身不检查就绪状态,调用方应先调用 isReady() |
matchesConditions(...) | 无强制检查 | 返回 false |
preview(...) | 无强制检查 | 返回失败结果,原因为“分解API尚未就绪” |
execute(...) | 必须在服务端主线程 | 返回 NOT_READY;非主线程优先返回 EXECUTION_ERROR |
reload() | 必须在服务端主线程 | 非主线程返回失败的重载结果 |
getHookStatus() | 无强制检查 | 返回当前适配器状态快照 |
getExtraButtons() | 无强制检查 | 返回当前额外按钮快照 |
createItem(...) | 接口未强制检查 | 调用方应先确认 API 和对应物品库适配器可用 |
replacePlaceholders(...) | 接口未强制检查 | PlaceholderAPI 不可用时返回原文 |
executeCommands(...) | 必须在服务端主线程 | 不执行任何命令 |
openGui(...) | 必须在服务端主线程 | 返回 false |
shutdown() | 应在插件停用流程的主线程调用 | 将 API 标记为未就绪并关闭分解界面 |
match(...)、规则读取方法和部分适配调用没有统一执行就绪检查。外部插件不应依赖其在 API 未就绪时的结果,应在业务入口统一检查 isReady()。
API 方法
状态与规则
| 方法 | 返回值 | 说明 |
|---|---|---|
isReady() | boolean | 判断 API 是否至少成功完成过一次配置加载,且尚未关闭 |
getRules() | List<DecompositionRuleData> | 获取当前全部只读规则,顺序与配置加载顺序一致 |
getGlobalConditions() | List<String> | 获取所有规则匹配前必须满足的只读全局条件 |
getRule(String ruleId) | DecompositionRuleData | 按规则 ID 获取只读规则,找不到时返回 null |
getHookStatus() | Map<String, DecompositionHookStatus> | 获取物品库、仓库、PlaceholderAPI 等适配器的运行状态 |
getExtraButtons() | Map<Integer, ExtraButtonData> | 获取当前额外按钮的不可变数据,键为底部按钮槽位 0 至 8 |
getRules() 返回的数据不会暴露插件内部的可变规则对象。规则中的条件、产物定义和命令列表同样为只读列表。
重新加载失败时,当前已经生效的规则、额外按钮、全局条件和产物入库顺序不会被失败配置替换。因此,重载失败后读取这些方法,仍可能得到上一次成功加载的数据。
条件匹配
java
DecompositionMatchResult match(Player player, ItemStack item)match(...) 先检查全局条件,再按配置顺序查找全部匹配规则。同一物品可以同时匹配多条规则,不会在第一条规则匹配后停止。
java
boolean matchesConditions(
Player player,
ItemStack item,
List<String> conditions
)matchesConditions(...) 使用插件内置条件解析器判断调用方提供的条件列表,不会自动追加主配置中的全局条件。
条件列表遵循以下逻辑:
- 多行条件之间为 AND,必须全部成立。
- 单行顶层使用
||分隔时为 OR,任意分支成立即可。 - 函数前可以添加一个或多个
!,奇数次表示取反,偶数次恢复原结果。 - 单引号和括号内的
||不会被当作顶层 OR 分隔符。 match(...)会自动应用global-condition。matchesConditions(...)只判断调用方传入的条件列表。- API 未就绪时,
matchesConditions(...)返回false。 - 玩家为
null时,permission(...)和papi(...)无法匹配;仅依赖物品的条件仍可参与判断。
支持的条件函数:
| 函数 | 说明 |
|---|---|
hasname() | 判断物品是否存在自定义名称 |
haslore() | 判断物品是否存在 Lore |
name(...) | 按指定方式匹配物品名称 |
lore(...) | 按指定方式匹配任意一行 Lore |
material(...) | 匹配数字 ID、数字 ID 与 Data,或材质名称 |
permission(...) | 判断玩家是否拥有指定权限 |
papi(...) | 替换 PlaceholderAPI 变量后判断比较表达式 |
hasnbt(...) | 判断物品是否存在指定 NBT 键或点号路径 |
nbt(...) | 读取 NBT 值并执行文本或数值比较 |
依赖限制:
papi(...)依赖 PlaceholderAPI。适配器不可用时条件不会匹配,包含该条件的配置也会在重载校验时报错。hasnbt(...)和nbt(...)依赖当前服务端版本对应的 NBT 适配器。适配器不可用时条件不会匹配,包含该条件的配置也会在重载校验时报错。
条件的完整写法与规则配置页一致,此处仅说明 API 的调用行为。
产物预览
java
DecompositionPreviewResult preview(Player player, ItemStack item)该方法生成不会触发概率随机、命令执行或物品发放的预览结果。
预览流程:
- 检查 API 是否就绪。
- 应用全局条件并查找全部匹配规则。
- 跳过
give-item: false的规则产物。 - 解析每条产物定义。
- 通过对应物品库创建展示物品。
- 将展示物品数量设置为产物最大数量,但不会超过该物品的最大堆叠数量。
预览会展示所有能够成功创建的候选产物,不进行概率随机,也不会执行规则命令和产物级命令。
部分产物无法解析或创建时,其余有效产物仍可正常返回。此时 isSuccess() 可以为 true,同时 getReason() 返回首个预览问题。没有任何可展示产物且已经出现预览问题时,结果为失败。
| 结果方法 | 返回值 | 说明 |
|---|---|---|
isSuccess() | boolean | 是否成功完成预览生成 |
getReason() | String | 失败原因,或部分产物无法预览时的首个问题 |
getRules() | List<DecompositionRuleData> | 当前物品匹配到的规则 |
getItems() | List<DecompositionPreviewItem> | 成功创建的产物预览 |
没有匹配到规则时,预览结果为失败,原因为“没有匹配到分解规则”。
执行分解
java
DecompositionExecutionResult execute(
Player player,
ItemStack item,
String sourceName
)该方法执行一个输入物品的完整分解流程,包括规则匹配、前置事件、概率随机、产物创建、产物投递、产物级命令、规则命令和后置事件。
参数说明:
| 参数 | 说明 |
|---|---|
player | 执行分解的玩家,也是权限、PlaceholderAPI、物品库和仓库调用的玩家上下文 |
item | 用于匹配和触发事件的输入物品;API 不会从玩家背包或调用方容器中移除该物品 |
sourceName | 结果消息中 {name} 的来源名称;传入 null 时使用“物品” |
调用方必须遵守以下规则:
- 只能在服务端主线程调用。
- 只能在
result.isSuccess()返回true后扣除输入物品。 - API 本身不会修改或移除调用方提供的输入物品。
- 不要在调用
execute(...)前提前扣除物品。 - 不要再次发放
getGeneratedItems()返回的物品,它们已经完成投递。
提前扣除输入物品会导致取消事件、配置错误或执行异常时无法安全恢复物品。
执行顺序如下:
- 检查主线程、API 状态、玩家和输入物品。
- 应用全局条件并查找全部匹配规则。
- 触发可取消的
DecompositionPreEvent。 - 按匹配规则顺序解析产物,并分别进行概率与数量随机。
- 创建本次实际命中的产物。
- 按
delivery-order依次投递每个产物。 - 发送当前产物的结果消息。
- 执行当前产物定义中使用
{命令}配置的产物级命令。 - 执行所有匹配规则的
commands命令。 - 创建成功结果并触发
DecompositionPostEvent。
同一个物品可以同时匹配多条规则。API 会叠加所有匹配规则的产物、产物级命令和规则命令。
产物按照主配置中的入库顺序依次尝试。当前目标无法完全接收时,剩余数量继续交给下一个目标;全部目标处理后仍有剩余时,物品会掉落在玩家位置,并在结果中写入警告。
输入物品管理
execute(...) 接收的 ItemStack 仅用于匹配、事件数据和执行上下文,不代表插件可以控制该物品所在的背包或容器。
推荐流程:
- 从调用方自己的容器中读取物品。
- 调用
execute(...)。 - 检查
isSuccess()。 - 成功后由调用方扣除对应数量的输入物品。
- 读取
getWarnings()并按需要记录警告。
执行状态
DecompositionExecutionResult#getStatus() 返回 DecompositionExecutionStatus。
| 状态 | 当前含义 |
|---|---|
SUCCESS | 分解主流程已完成;仍需检查警告列表 |
NOT_READY | API 尚未成功加载,或已经关闭 |
INVALID_ITEM | 玩家为空,或输入物品为空、空气、数量不大于零 |
NO_MATCH | 输入物品没有匹配到任何分解规则 |
CANCELLED | DecompositionPreEvent 被外部插件取消 |
INVENTORY_FULL | 枚举中保留的背包空间不足状态;当前执行实现不会返回该状态 |
CONFIG_ERROR | 产物配置错误,或物品库无法创建配置的产物 |
EXECUTION_ERROR | 非主线程调用,或执行过程中出现异常 |
当前产物投递会继续尝试后续仓库,最终仍有剩余时直接掉落在玩家位置。因此,背包无法完全容纳产物不会直接导致 INVENTORY_FULL。
执行结果
| 结果方法 | 返回值 | 说明 |
|---|---|---|
isSuccess() | boolean | 状态是否为 SUCCESS |
getStatus() | DecompositionExecutionStatus | 获取完整执行状态 |
getReason() | String | 获取状态对应的简体中文原因;成功时通常为空字符串 |
getRequiredSlots() | int | 获取仍需的背包槽位数量;当前执行实现返回 0 |
getRules() | List<DecompositionRuleData> | 获取本次匹配到的规则 |
getGeneratedItems() | List<ItemStack> | 获取本次实际生成并进入投递流程的物品副本 |
getWarnings() | List<String> | 获取不改变主要执行状态的警告 |
getGeneratedItems() 每次都会返回独立的物品副本。修改返回的 ItemStack 不会修改结果对象内部保存的数据。
产物投递、产物级命令或规则命令出现后续异常时,插件会尽量保留成功主状态,并将问题写入 getWarnings()。调用方不能只检查 isSuccess(),还应读取警告列表。
DecompositionPostEvent 只会在执行流程进入成功结果后触发。NOT_READY、INVALID_ITEM、NO_MATCH、CANCELLED、CONFIG_ERROR 和 EXECUTION_ERROR 不会触发后置事件。
重载接口
java
DecompositionReloadResult reload()reload() 会重新读取并校验以下内容:
- 主配置
config.yml。 rule目录及其子目录中的全部.yml文件。- 全局条件。
- 产物入库顺序。
- 额外按钮。
- 物品库、仓库、PlaceholderAPI 和 NBT 适配状态。
规则文件会递归读取,并按完整路径忽略大小写排序。每个规则文件的最外层节点为规则 ID,规则 ID 必须在全部文件中全局唯一。
重载会严格检查:
- 主配置是否包含不支持的根字段。
delivery-order是否为有效且不重复的字符串列表。global-condition是否为非空字符串列表并符合条件语法。- 规则是否只包含
condition、give-item、commands和result。 - 每条规则是否至少包含一行条件。
- 产物数量、概率、物品库和产物级命令格式。
- PlaceholderAPI 与 NBT 条件需要的适配器是否可用。
- 额外按钮槽位、动作、条件、冷却和命令格式。
存在阻止加载的错误时,不会替换当前规则、按钮、全局条件和入库顺序。首次加载失败时,API 不会进入就绪状态;已经成功加载过的实例会继续保留上一次有效数据。
reload() 必须在服务端主线程调用。
| 结果方法 | 返回值 | 说明 |
|---|---|---|
isSuccess() | boolean | 是否成功替换当前运行数据 |
getRuleCount() | int | 本次读取并暂存的规则数量 |
getButtonCount() | int | 本次读取并暂存的额外按钮数量 |
getWarnings() | List<String> | 不阻止重载的问题 |
getErrors() | List<String> | 阻止重载的问题 |
重载失败时,getRuleCount() 和 getButtonCount() 仍可能大于 0,它们表示本次已经读取到的数据数量,不表示这些数据已经生效。是否成功应用必须以 isSuccess() 为准。
外部适配调用
创建物品
java
ItemStack createItem(Player player, String itemId)通过插件统一物品库适配器创建物品。无法识别物品库、适配器不可用或物品不存在时返回 null。
itemId 可以直接填写物品 ID,也可以使用 物品库@物品ID 明确指定来源:
text
MythicMobs@分解产物1
AzureFlow@材料
NeigeItems@装备未填写物品库前缀时,使用主配置 item-provider 指定的默认物品库。该配置为空时回退为 MythicMobs。
项目中确认支持以下物品库名称:
| 物品库 | 说明 |
|---|---|
MythicMobs | 支持 MythicMobs 4 与 MythicMobs 5 适配 |
LyItemSave | 与 MythicMobs 名称互通,任意一方可用时两个名称均可使用 |
AzureFlow | 外部物品库适配 |
NeonFlash | 外部物品库适配 |
SX-Item | 外部物品库适配 |
NeigeItems | 外部物品库适配 |
OriginAttribute | 外部物品库适配 |
具体适配器是否可以安全调用,应通过 getHookStatus() 查询,不要只根据服务器插件列表判断。
查询适配器状态
java
Map<String, DecompositionHookStatus> getHookStatus()返回当前外部适配器状态。状态可能包含物品库、仓库和 PlaceholderAPI 等外部功能。
java
// hookStatuses 保存当前全部外部适配器状态。
Map<String, DecompositionHookStatus> hookStatuses = decompositionApi.getHookStatus();
// mythicMobsStatus 保存 MythicMobs 适配器状态,键不存在时为 null。
DecompositionHookStatus mythicMobsStatus = hookStatuses.get("MythicMobs");
if (mythicMobsStatus != null && mythicMobsStatus.isAvailable()) {
// createdItem 保存物品库创建的物品。
ItemStack createdItem = decompositionApi.createItem(player, "MythicMobs@材料");
}返回映射及其中的状态对象用于读取,不应尝试修改插件内部适配器状态。
替换变量
java
String replacePlaceholders(Player player, String source)使用当前可用的 PlaceholderAPI 适配器替换玩家变量。
| 情况 | 返回结果 |
|---|---|
| PlaceholderAPI 可用 | 返回替换后的文本 |
| PlaceholderAPI 不可用 | 返回原文 |
source 为 null | 返回空字符串 |
该方法只负责变量替换,不判断替换后的文本是否符合条件表达式或命令格式。
执行命令
java
void executeCommands(Player player, List<String> commands)按列表顺序执行命令。命令执行前会替换 PlaceholderAPI 变量。
| 格式 | 执行身份 |
|---|---|
[console]命令 | 控制台 |
[op]命令 | 临时给予玩家 OP 后执行,结束后恢复原状态 |
命令 | 玩家 |
身份前缀忽略英文大小写。空命令会被跳过,单条命令异常不会阻止后续命令继续执行。
出现以下情况时,该方法不会执行任何命令:
- API 未就绪。
- 玩家为
null。 - 命令列表为
null。 - 当前线程不是服务端主线程。
[op] 会临时修改玩家 OP 状态。即使命令执行出现异常,插件也会尝试恢复玩家原本的 OP 状态。
打开界面
java
boolean openGui(Player player)满足以下全部条件时,为玩家打开分解界面并返回 true:
- API 已就绪。
- 玩家不为
null。 - 当前位于服务端主线程。
任一条件不满足时返回 false。
关闭 API
java
void shutdown()该方法会执行以下操作:
- 将 API 标记为未就绪。
- 关闭所有仍在使用分解界面的在线玩家界面。
- 重置核心初始化状态。
该方法用于插件停用或核心关闭流程,不应作为普通配置重载方法使用。关闭后需要由插件自身重新完成初始化和配置加载,外部插件不能通过普通业务调用恢复 API。
数据对象
公共数据对象位于以下包中:
java
Ly.galaxy.decomposition.client.plugin.api.dataDecompositionRuleData
只读规则数据。
| 方法 | 返回值 | 说明 |
|---|---|---|
getId() | String | 规则唯一 ID |
isGiveItem() | boolean | 是否发放 result 中的产物 |
getConditions() | List<String> | 规则条件列表 |
getResults() | List<String> | 原始产物定义列表 |
getCommands() | List<String> | 规则执行命令列表 |
DecompositionMatchResult
| 方法 | 返回值 | 说明 |
|---|---|---|
isMatched() | boolean | 是否至少匹配到一条规则 |
getRules() | List<DecompositionRuleData> | 按配置顺序排列的匹配规则 |
DecompositionPreviewResult
| 方法 | 返回值 | 说明 |
|---|---|---|
isSuccess() | boolean | 是否成功完成产物预览 |
getReason() | String | 失败原因或首个部分预览问题 |
getRules() | List<DecompositionRuleData> | 当前输入物品匹配到的规则 |
getItems() | List<DecompositionPreviewItem> | 成功创建的预览物品 |
DecompositionPreviewItem
| 方法 | 返回值 | 说明 |
|---|---|---|
getProduct() | DecompositionProductData | 获取解析后的产物定义 |
getItem() | ItemStack | 获取独立的预览物品副本 |
DecompositionProductData
| 方法 | 返回值 | 说明 |
|---|---|---|
getRuleId() | String | 所属规则 ID |
getItemId() | String | 物品库物品 ID,可能包含物品库前缀 |
getMinimumAmount() | int | 最小产物数量 |
getMaximumAmount() | int | 最大产物数量 |
getChance() | double | 出现概率,范围为 0 至 1 |
getCommands() | List<String> | 当前产物命中并投递后执行的命令 |
产物定义的命令不会在 preview(...) 中执行,只会在 execute(...) 实际随机命中该产物后执行。
DecompositionExecutionResult
| 方法 | 返回值 | 说明 |
|---|---|---|
isSuccess() | boolean | 状态是否为 SUCCESS |
getStatus() | DecompositionExecutionStatus | 获取执行状态 |
getReason() | String | 获取状态原因 |
getRequiredSlots() | int | 获取仍需的背包槽位数量 |
getRules() | List<DecompositionRuleData> | 获取匹配规则 |
getGeneratedItems() | List<ItemStack> | 获取实际生成物品的独立副本 |
getWarnings() | List<String> | 获取非致命警告 |
DecompositionReloadResult
| 方法 | 返回值 | 说明 |
|---|---|---|
isSuccess() | boolean | 是否成功替换运行数据 |
getRuleCount() | int | 本次读取的规则数量 |
getButtonCount() | int | 本次读取的额外按钮数量 |
getWarnings() | List<String> | 获取重载警告 |
getErrors() | List<String> | 获取阻止重载的问题 |
DecompositionHookStatus
| 方法 | 返回值 | 说明 |
|---|---|---|
getName() | String | 外部插件或适配器名称 |
isAvailable() | boolean | 当前是否可以安全调用 |
getMessage() | String | 当前状态说明 |
Bukkit 事件
事件位于以下包中:
java
Ly.galaxy.decomposition.client.plugin.api.eventDecompositionPreEvent
完整类名:
java
Ly.galaxy.decomposition.client.plugin.api.event.DecompositionPreEvent该事件在概率随机、产物创建、物品投递和命令执行之前触发,可以取消。
| 方法 | 返回值 | 说明 |
|---|---|---|
getPlayer() | Player | 获取执行分解的玩家 |
getInputItem() | ItemStack | 获取本次输入物品的独立副本 |
getRules() | List<DecompositionRuleData> | 获取本次匹配到的只读规则 |
isCancelled() | boolean | 判断事件是否已取消 |
setCancelled(boolean cancelled) | void | 设置取消状态 |
事件被取消后,execute(...) 返回 CANCELLED,不会随机产物、创建或发放物品、执行命令,也不会触发 DecompositionPostEvent。输入物品仍由调用方管理。
java
import Ly.galaxy.decomposition.client.plugin.api.event.DecompositionPreEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public final class DecompositionListener implements Listener {
/** 在分解执行前检查并按业务需要取消操作。 */
@EventHandler
public void onDecompositionPre(DecompositionPreEvent event) {
if (event.getRules().isEmpty()) {
event.setCancelled(true);
}
}
}DecompositionPostEvent
完整类名:
java
Ly.galaxy.decomposition.client.plugin.api.event.DecompositionPostEvent该事件在产物投递、产物级命令和规则命令处理结束后触发,为只读事件。
| 方法 | 返回值 | 说明 |
|---|---|---|
getPlayer() | Player | 获取执行分解的玩家 |
getInputItem() | ItemStack | 获取本次输入物品的独立副本 |
getResult() | DecompositionExecutionResult | 获取本次完整执行结果 |
java
import Ly.galaxy.decomposition.client.plugin.api.data.DecompositionExecutionResult;
import Ly.galaxy.decomposition.client.plugin.api.event.DecompositionPostEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public final class DecompositionResultListener implements Listener {
/** 在分解完成后读取实际产物和非致命警告。 */
@EventHandler
public void onDecompositionPost(DecompositionPostEvent event) {
// executionResult 保存本次分解的完整执行结果。
DecompositionExecutionResult executionResult = event.getResult();
// generatedItemCount 保存本次实际生成的产物种类数量。
int generatedItemCount = executionResult.getGeneratedItems().size();
// warningCount 保存本次执行产生的非致命警告数量。
int warningCount = executionResult.getWarnings().size();
}
}事件中的输入物品均为副本。修改事件返回的物品不会直接修改调用方原物品。
完整调用流程
java
import Ly.galaxy.decomposition.client.license.Start;
import Ly.galaxy.decomposition.client.plugin.api.LyDecompositionAPI;
import Ly.galaxy.decomposition.client.plugin.api.data.DecompositionExecutionResult;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/** 尝试执行一次分解,并仅在成功后处理输入物品。 */
public boolean decomposeItem(Player player, ItemStack inputItem) {
// decompositionApi 保存插件当前提供的公共分解接口。
LyDecompositionAPI decompositionApi = Start.getAPI();
if (decompositionApi == null || !decompositionApi.isReady()) {
return false;
}
// sourceName 保存结果消息中显示的输入物品名称。
String sourceName = inputItem.hasItemMeta()
&& inputItem.getItemMeta().hasDisplayName()
? inputItem.getItemMeta().getDisplayName()
: inputItem.getType().name();
// executionResult 保存产物投递、命令和事件处理后的完整结果。
DecompositionExecutionResult executionResult = decompositionApi.execute(
player,
inputItem,
sourceName
);
if (!executionResult.isSuccess()) {
return false;
}
// 此处由调用方根据自身容器逻辑扣除对应输入物品。
return true;
}该方法必须由服务端主线程调用。如果调用入口可能位于异步任务中,应先切换回 Bukkit 主线程,再调用 execute(...)。
注意事项
execute(...)已包含产物创建、产物投递、产物级命令和规则命令,不要重复处理这些动作。getGeneratedItems()用于读取执行结果,不代表尚未发放的待处理物品。preview(...)不进行概率随机,不能用预览列表代替实际执行结果。- 预览物品数量使用产物最大值,不代表实际分解一定得到该数量。
- 同一物品可能匹配多条规则,调用方不能假定只返回第一条规则。
DecompositionPreEvent中的输入物品和规则数据用于读取,不会直接修改调用方原物品或插件内部规则。DecompositionPostEvent只在成功主流程中触发,失败和取消结果需要直接读取execute(...)返回值。- 配置重载失败时,应读取
DecompositionReloadResult#getErrors(),不要仅依赖控制台文本。 - 重载失败不会替换上一份有效规则,但本次读取数量仍可能大于
0。 - 调用物品库、仓库或 PlaceholderAPI 前,可以通过
getHookStatus()判断对应适配器是否可用。 - API 不负责扣除输入物品。提前扣除会破坏取消事件和失败状态下的数据安全。
SUCCESS不代表完全没有后续问题,调用方还应检查getWarnings()。- 当前背包无法容纳的剩余产物会继续尝试后续仓库,最终无法接收的部分会掉落在玩家位置。
shutdown()用于插件生命周期结束,不应代替reload()。