深色模式
公开 API
包名:cn.sealplugins.items.api
SealItemsApi
kotlin
interface SealItemsApi {
fun openIdentification(playerUuid: UUID): IdentificationOpenResponse
}参数
playerUuid 是目标玩家 UUID。调用时玩家通常应在线;API 接受 UUID 是为了避免公共契约直接泄漏 Bukkit Player 类型。
返回
kotlin
data class IdentificationOpenResponse(
val opened: Boolean,
val reason: String? = null,
)opened=true:服务端已接受打开请求。opened=false:没有打开;reason可能解释原因。reason可为空,调用方必须提供自己的 fallback。
该方法不承诺 GUI 一定是原版或 ArcartX;实际 provider 由服务端配置和玩家资源就绪状态决定。
Kotlin 完整示例
kotlin
package com.example.mysealaddon
import cn.sealplugins.items.api.SealItemsApi
import org.bukkit.entity.Player
import org.bukkit.plugin.java.JavaPlugin
class MySealAddon : JavaPlugin() {
fun openIdentificationFor(player: Player) {
val api = server.servicesManager.load(SealItemsApi::class.java)
if (api == null) {
player.sendMessage("§c鉴定服务当前未安装或尚未就绪。")
return
}
val response = runCatching {
api.openIdentification(player.uniqueId)
}.getOrElse { failure ->
logger.warning("调用 SealItems 鉴定 API 失败:${failure.message}")
player.sendMessage("§c鉴定服务暂时发生异常。")
return
}
if (!response.opened) {
player.sendMessage("§c无法打开鉴定:${response.reason ?: "未知原因"}")
}
}
}runCatching 只用于隔离跨插件异常,不应吞掉日志;业务拒绝仍通过 response 处理。
Java 完整示例
java
package com.example.mysealaddon;
import cn.sealplugins.items.api.IdentificationOpenResponse;
import cn.sealplugins.items.api.SealItemsApi;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public final class MySealAddon extends JavaPlugin {
public void openIdentificationFor(Player player) {
SealItemsApi api = getServer().getServicesManager().load(SealItemsApi.class);
if (api == null) {
player.sendMessage("§c鉴定服务当前未安装或尚未就绪。");
return;
}
try {
IdentificationOpenResponse result =
api.openIdentification(player.getUniqueId());
if (!result.getOpened()) {
String reason = result.getReason() == null
? "未知原因"
: result.getReason();
player.sendMessage("§c无法打开鉴定:" + reason);
}
} catch (RuntimeException exception) {
getLogger().warning("调用 SealItems 鉴定 API 失败:" + exception.getMessage());
player.sendMessage("§c鉴定服务暂时发生异常。");
}
}
}Kotlin data class 对 Java 暴露 getOpened() 和 getReason()。
服务生命周期示例
简单插件在每次命令时重新 load 就足够。若缓存:
java
private volatile SealItemsApi sealItems;
@Override
public void onEnable() {
refreshSealItems();
}
private void refreshSealItems() {
sealItems = getServer().getServicesManager().load(SealItemsApi.class);
}
@Override
public void onDisable() {
sealItems = null;
}还必须监听服务注册/注销或在每次使用前验证。仅在 onEnable 获取一次会在 /reload、插件管理器重载或启动顺序变化后持有失效引用。
当前没有的公共 API
以下能力虽在插件内部存在,但不是公共契约:
- 按 ID 发放物品;
- 直接构建 ItemStack;
- 读取/写入物品 PDC;
- 请求物品迁移;
- 打开改造/宝石工作台;
- 提交重铸、洗炼或孔位操作;
- 读取所有物品/词条/品质快照;
- 订阅内部事务事件。
不要通过反射、内部包依赖或复制 codec 绕过。内部类可随开发快照变化,也会破坏服务端的权限、费用、CAS 和审计保护。
提议新 API 时应说明
调用者是谁、线程、输入与稳定身份、权限由谁负责、失败枚举、幂等性、插件禁用时行为、是否会触发费用/随机、数据兼容承诺和最小用例。优先增加小而不可误用的接口。