Skip to content

这页面向 想从别的插件读取或调用 HNWarehouse 能力的开发者


当前公开入口

当前静态 API 入口类是:

  • com.github.hnplugins.hnwarehouse.api.HNWarehouseAPI

它当前已经公开:

  • getServices()
  • deliverItem(...)
  • deliverReward(...)
  • deliverAutoCollect(...)
  • deliverToWarehouse(...)
  • withdraw(...)
  • withdrawToInventory(...)
  • getSummary(...)
  • getWarehouseSummary(...)
  • 若干访问状态判断方法

另外还提供了工具类 ItemDeliveryResultUtils 用于处理投递结果:

  • hasBlockedWarehouses(result)
  • getBlockedWarehouseIds(result)
  • getBlockedWarehouseReasonMap(result)
  • describeBlockedWarehouses(result)

接入前提

插件依赖

如果你的插件要直接编译期调用 HNWarehouse API,通常应至少保证:

  • HNCore
  • HNWarehouse

都在你的运行环境中可用。

运行时判断

建议在真正调用前先确认插件已加载:

java
Plugin plugin = Bukkit.getPluginManager().getPlugin("HNWarehouse");
if (plugin == null || !plugin.isEnabled()) {
    return;
}

如果你的业务逻辑允许“有仓库就入仓,没有仓库就走普通发奖”,那这里最好做成可回退流程,而不是硬崩。

关于 reload 窗口

当前 HNWarehouse 的管理员重载已经改成后台执行

这意味着:

  • 插件本体仍然是启用状态,但重载窗口里运行时服务可能暂时不可用
  • HNWarehouseAPI.getServices() 不适合被下游长期缓存后反复直接使用
  • 更稳妥的做法是:每次真正调用前重新获取服务,或在调用点做好降级 / 跳过 / 重试保护

如果你的业务属于“高频触发、不能接受偶发不可用窗口”,建议额外做:

  • 插件可用性判断
  • 调用失败后的回退流程
  • 避免把 HNWarehouseServices 保存成长期单例引用

可以做什么

通过当前 API,你已经可以:

  • 把一件物品按默认来源投递到玩家仓库
  • 显式投递到指定仓库
  • 预判投递结果中的被拦截仓库信息
  • 查询玩家整体仓库摘要与单仓库摘要
  • 判断仓库当前是否可访问、是否锁定、是否需要解锁
  • 从指定条目执行提取 / 回填背包

例如你可以基于它做:

  • 任务奖励自动入仓
  • 签到奖励或补偿奖励自动入仓
  • 其他插件的“共享仓库入口”
  • 面板类查询展示
  • 条件判断:某个仓库当前是否开放

最常见的三种接入方式

1. 把奖励直接送进仓库

java
import com.github.hnplugins.hnwarehouse.api.HNWarehouseAPI;
import com.github.hnplugins.hnwarehouse.api.ItemDeliveryResultUtils;
import com.github.hnplugins.hnwarehouse.service.result.ItemDeliveryResult;
import org.bukkit.inventory.ItemStack;

UUID playerId = player.getUniqueId();
ItemStack reward = new ItemStack(Material.DIAMOND, 8);

ItemDeliveryResult result = HNWarehouseAPI.deliverReward(playerId, reward);
if (result.deliveredAmount() <= 0) {
    player.sendMessage("奖励入仓失败:" + ItemDeliveryResultUtils.describeBlockedWarehouses(result));
}

适合:

  • 奖励型业务
  • 补偿邮件转仓库
  • 活动奖励自动入仓

2. 显式投到指定仓库

java
ItemDeliveryResult result = HNWarehouseAPI.deliverToWarehouse(
        player.getUniqueId(),
        "reward",
        ItemDeliverySource.REWARD,
        itemStack
);

适合:

  • 业务侧已经明确知道目标仓库
  • 但仍想复用 HNWarehouse 的访问规则、页面路由与 item-admission

3. 先判断仓库可不可用,再决定怎么处理

java
String warehouseId = "main";
if (!HNWarehouseAPI.isWarehouseAccessible(player.getUniqueId(), warehouseId)) {
    String reason = HNWarehouseAPI.getWarehouseDenialReason(player.getUniqueId(), warehouseId);
    player.sendMessage("仓库当前不可用:" + reason);
    return;
}

WarehouseSummary summary = HNWarehouseAPI.getWarehouseSummary(player.getUniqueId(), warehouseId);
player.sendMessage("当前仓库页数:" + summary.totalPages());

适合:

  • 打开面板前预检
  • 业务入口做动态开放判断
  • 运营活动只对已开放仓库生效

投递相关入口

默认投递

  • deliverItem(UUID, ItemStack)
  • deliverReward(UUID, ItemStack)
  • deliverAutoCollect(UUID, ItemStack)

适合场景:

  • 由来源语义直接决定默认目标仓库
  • 下游只关心“把物品交给仓库系统”,不关心具体落哪一页

指定仓库投递

  • deliverToWarehouse(UUID, String, ItemStack)
  • deliverToWarehouse(UUID, String, ItemDeliverySource, ItemStack)

适合场景:

  • 业务侧明确知道应该进入哪个仓库
  • 但仍希望复用仓库访问规则、页面路由与 item-admission

被拦截仓库辅助方法

当使用投递 API 后,可以通过以下工具方法检查投递结果中被拦截的仓库信息:

hasBlockedWarehouses(result)

检查投递结果中是否有被拦截的仓库。

java
ItemDeliveryResult result = HNWarehouseAPI.deliverItem(playerId, itemStack);
if (ItemDeliveryResultUtils.hasBlockedWarehouses(result)) {
    // 有仓库被拦截,需要处理
}

getBlockedWarehouseIds(result)

获取所有被拦截的仓库 ID 列表。

java
List<String> blockedIds = ItemDeliveryResultUtils.getBlockedWarehouseIds(result);
player.sendMessage("以下仓库拒绝了物品:" + String.join(", ", blockedIds));

getBlockedWarehouseReasonMap(result)

获取被拦截仓库的详细原因映射(仓库 ID → 拦截原因)。

java
Map<String, String> reasonMap = ItemDeliveryResultUtils.getBlockedWarehouseReasonMap(result);
for (Map.Entry<String, String> entry : reasonMap.entrySet()) {
    player.sendMessage("仓库 " + entry.getKey() + " 拒绝原因:" + entry.getValue());
}

describeBlockedWarehouses(result)

生成被拦截仓库的可读描述文本。

java
String description = ItemDeliveryResultUtils.describeBlockedWarehouses(result);
if (!description.isEmpty()) {
    player.sendMessage("投递失败详情:\n" + description);
}

适合场景:

  • 做投递失败提示
  • 输出调试日志
  • 给管理面板展示"为什么没进去"
  • 帮助玩家理解物品为何被拒绝

提取相关入口

当前已提供:

  • withdraw(UUID, warehouseId, pageId, entryId)
  • withdraw(UUID, warehouseId, pageId, entryId, requestedAmount)
  • withdrawToInventory(UUID, warehouseId, pageId, entryId)
  • withdrawToInventory(UUID, warehouseId, pageId, entryId, requestedAmount)

示例:把指定条目提回玩家背包

java
import com.github.hnplugins.hnwarehouse.service.result.ItemWithdrawalResult;

ItemWithdrawalResult result = HNWarehouseAPI.withdrawToInventory(
        player.getUniqueId(),
        "main",
        "page-1",
        entryId,
        16
);

if (!result.isSuccessful()) {
    player.sendMessage("提取失败:" + result.failureReason());
    return;
}

player.sendMessage("提取成功,数量:" + result.withdrawnAmount());

使用建议:

  • 如果你要做“直接得到提取结果对象”,可用 withdraw(...)
  • 如果你要做“直接把物品送回玩家背包”,可用 withdrawToInventory(...)

查询相关入口

玩家整体摘要

  • getSummary(UUID)

说明:

  • 如果目标玩家当前在线,通常更接近运行时内存态摘要
  • 如果目标玩家离线,摘要查询可能命中短 TTL 缓存
  • 写入发生后,相关摘要缓存会主动失效

适合读取:

  • 总仓库数 / 总页数 / 总容量
  • 当前可访问仓库数与锁定仓库数
  • 各仓库摘要列表

示例:读取玩家总览

java
import com.github.hnplugins.hnwarehouse.view.PlayerStorageSummary;

PlayerStorageSummary summary = HNWarehouseAPI.getSummary(player.getUniqueId());
player.sendMessage("总仓库数:" + summary.totalWarehouses());
player.sendMessage("总页数:" + summary.totalPages());
player.sendMessage("可访问仓库:" + summary.accessibleWarehouses());

单仓库摘要

  • getWarehouseSummary(UUID, warehouseId)

适合读取:

  • 当前仓库是否可访问
  • 是否锁定
  • 是否属于“需要一次性解锁”的状态
  • 当前不可访问原因
  • 锁定时是否允许展示

示例:做仓库状态提示

java
WarehouseSummary summary = HNWarehouseAPI.getWarehouseSummary(player.getUniqueId(), "main");
if (summary.locked()) {
    player.sendMessage("仓库当前锁定,原因:" + summary.denialReason());
    if (summary.unlockRequired()) {
        player.sendMessage("这是可解锁仓库,可以引导玩家执行 /hnwarehouse unlock main");
    }
}

便捷判断方法

  • isWarehouseAccessible(...)
  • isWarehouseLocked(...)
  • requiresWarehouseUnlock(...)
  • getWarehouseDenialReason(...)
  • isWarehouseVisibleWhenLocked(...)

关于写操作的建议

虽然当前 API 已经开放了投递与提取写操作,但从下游接入角度,仍建议你:

  • 优先通过 API 调用统一 service,而不是自己改玩家 YAML
  • 不要绕过访问校验、页面路由或条目逻辑自己拼状态
  • 不要把 HNWarehouse 当成“一个纯 List<ItemStack> 容器”去硬写

原因是当前实际联动的不只是条目本身,还包括:

  • 仓库访问状态
  • 解锁 / 购买 / 扩容状态
  • 页面优先级与允许来源
  • item-admission 规则
  • 提取回背包时的在线玩家状态

与 HNCore 的关系

HNWarehouse 当前依赖 HNCore 的公共能力,尤其是:

  • 公共日志能力
  • 公共命令注册能力
  • 共享物品库入口
  • 物品身份协议与 PDC 约定的协作边界

如果你只是想复用公共基础能力,优先直接看 HNCore;如果你想复用“仓库路由、访问控制、条目提取”这一层业务语义,再看 HNWarehouse。


当前 API 的边界

当前版本更偏向:

  • 业务接入可用
  • 查询与统一投递可用
  • 仓库系统骨架已稳定
  • 但仍不是一个已经完全成熟的“仓储 SDK”

尤其要注意:

  • 自动收纳监听器等部分能力仍在骨架阶段
  • 原版背包投影与更深层接管尚未完整接入
  • GUI 流程当前可用,但玩家入口还不是最终形态

也就是说,它已经足够拿来做:

  • 奖励入仓
  • 查询展示
  • 管理命令联动
  • 仓库状态判断

但如果你想做“完全接管玩家所有物品流转”,目前仍建议结合源码与真实场景逐步接入。


新功能(v0.1.0-SNAPSHOT)

搜索功能

HNWarehouse 现已集成 HNCore 2.3.0 的搜索框架,为仓库页面提供智能物品搜索功能。

功能特性

  • 智能相关度评分:完全匹配 > 开头匹配 > 包含匹配 > 类型匹配 > ID 匹配
  • 多字段搜索:支持按物品名称、类型、条目 ID 搜索
  • 搜索结果分页:每页显示 45 个结果,支持翻页浏览
  • 直接提取:可从搜索结果直接提取物品
  • 审计日志:所有搜索操作都会记录

使用方式

玩家在仓库页面 GUI 中:

  1. 点击搜索图标(望远镜,槽位 47)
  2. 在聊天框输入搜索关键词
  3. 查看搜索结果 GUI
  4. 点击物品提取或翻页查看更多

取消搜索

输入 cancel取消 可取消搜索操作。

输入会话框架

取款数量输入功能已改造为使用 HNCore 2.3.0 的统一输入会话框架。

功能特性

  • 统一会话管理:自动处理会话生命周期
  • 自动超时:60 秒无输入自动超时并重新打开页面
  • 线程安全:使用 ConcurrentHashMap 管理会话
  • 输入验证:支持正整数、"cancel"、"取消"命令

使用方式

玩家在仓库页面 GUI 中:

  1. Shift + 右键点击物品
  2. 在聊天框输入要提取的数量
  3. 系统自动验证并执行提取

取消提取

输入 cancel取消 可取消提取操作。


推荐接入姿势

如果你只是想发一件奖励到玩家仓库

优先使用:

  • deliverReward(...)

如果你想把某类业务物品固定投到某个仓库

优先使用:

  • deliverToWarehouse(...)

如果你只是想判断某仓库当前能不能打开

优先读取:

  • getWarehouseSummary(...)
  • isWarehouseAccessible(...)
  • getWarehouseDenialReason(...)

如果你想做自己的管理面板

优先读取:

  • getSummary(...)
  • getWarehouseSummary(...)

不要直接读磁盘 YAML 再自己拼页面逻辑。

HN 系列插件文档