跳到正文
烈焰甘蔗Wiki

Applied Energistics 2 Integration

BetterBuildersWands 与 Applied Energistics 2(AE2)集成,支持 ME 网络库存查询和物品数量同步。

触发条件

此功能仅在检测到 AE2 模组加载时激活:

if (Loader.isModLoaded("appliedenergistics2")) {
    // 注册 AE2 相关网络包
}

BasicPlayerShim 在构造时把 aeEnabled 固定为 Loader.isModLoaded("appliedenergistics2")。 MEHandler 里的所有方法都标注了 @Optional.Method(modid = "appliedenergistics2"), 未安装 AE2 时这些代码被 Forge 剔除。

网络包

SynchronizeAEItemQuantity

让客户端知道 ME 网络里有多少目标方块 —— 客户端本身没有 AE2 网格访问权。

包类 discriminator 处理端 方向 载荷
SyncServer 1 Side.SERVER 客户端 → 服务端 ItemStack(ByteBufUtils.writeItemStack)
SyncClient 2 Side.CLIENT 服务端 → 客户端 int size(存入 BasicPlayerShim.AEItemSize)

Side.SERVER / Side.CLIENT 指的是处理端所在的一侧。 SyncServer 里的 “Server” 指的是"发给服务端处理的请求"。

服务端 SyncServer.onMessage 的回复逻辑:

情况 回复
取不到无线终端 GUI 对象,或 stack == null SyncClient(0)
obj.rangeCheck() 为假(超出范围) SyncClient(0)
网格中匹配到物品 SyncClient(min(found.getStackSize(), Integer.MAX_VALUE))
未匹配到 SyncClient(0)

客户端缓存策略

BasicPlayerShim.getAEItem 的客户端分支:

情况 行为
查询的物品变了 立即发 SyncServer,返回上一次缓存的 AEItemSize
物品没变,且 worldObj.getTotalWorldTime() % 10 == 0 每 10 个世界刻(0.5 秒)发一次
玩家身上没有任何无线终端 AEItemSize = 0

因为回复是异步的,第一次查询某个新物品时返回的是上一次的缓存值(可能是 0), 所以"刚切换目标方块时放不出方块"是预期行为,等 0.5 秒后重试即可。

MEHandler

MEHandler.java 负责定位玩家的 AE2 无线终端,并做权限/电量校验:

终端搜索顺序

顺序 来源
1 主背包 player.inventory(36 格)
2 Baubles 饰品栏(需安装 Baubles,见 Baubles 集成)

命中的槽位会传给 getTerminalGuiObject(item, player, x, y),其中 主背包命中传 y = 0、饰品栏命中传 y = 1(影响 AE2 GUI 的定位行)。

取到 GUI 对象后的校验链

校验 不通过的后果
Platform.isClient()(必须服务端执行) 返回 null
item.getItem() instanceof IWirelessTermHandler 返回 null
handler.canHandle(item) 返回 null
registry.isWirelessTerminal(item) 返回 null
handler.getEncryptionKey(item) 非空 返回 null
key 对应的 ILocatable 是 TileSecurity 返回 null
handler.hasPower(player, 1000F, item) 返回 null
obj.rangeCheck() 数量按 0 计

⚠️ 必须把无线终端绑定到一个 AE2 安全站(Security Station), 否则查不到 TileSecurity,整个 AE2 集成对本玩家失效。 还要消耗 1000 AE 的检查功率。

与材料扣取的联动

BasicPlayerShim.countItems 会把 AE2 网络数量累加进总数(SIMULATE,不真扣):

if (aeEnabled) total += getAEItem(itemStack, Integer.MAX_VALUE - total, false);
return itemStack.stackSize > 0 ? total / itemStack.stackSize : 0;

BasicPlayerShim.useItem 则优先从 AE2 真扣(MODULATE):

if (aeEnabled) {
    toUse += getAEItem(itemStack, needUse, true);
    if (toUse >= needUse) return needUse;
}

getAEItem 的服务端分支还要求 EXTRACT 权限:

if (MEHandler.securityCheck(player, obj.getGrid(), SecurityPermissions.EXTRACT)) {
    … inventory.extractItems(…, Actionable.MODULATE, new PlayerSource(player, obj)) …
}

AE2 在材料来源中的优先级(useItem 顺序):

优先级 来源
1 Ztones ofanix(目标是圆石时直接返回全额,不扣任何东西)
2 AE2 网络(真扣)
3 背包(按 slotPriority 反向扣,热键栏留到最后)
4 Botania IBlockProvider(见 Botania 集成)

使用场景

当玩家使用魔杖放置需要从 ME 网络提取大量相同方块的建筑时:

  1. getProperItemStack 取出目标物品(若装了 Backhand 则取副手)
  2. countItems = 背包 + Botania 花盆 + AE2 网络,三者求和
  3. numBlocks = min(wand.getMaxBlocks(itemstack), countItems) —— 魔杖等级与 AE2 库存取小
  4. BFS 搜索出 numBlocks 个坐标
  5. useItem 先从 AE2 抽,AE2 不够再从背包抽

⚠️ 因为取 min,AE2 库存再大也不会突破魔杖等级上限 (Diamond Wand 封顶 1561,Unbreakable Wand 各 meta 见 魔杖等级系统)。AE2 集成的价值在于不受背包容量限制, 而不在于提高上限。

相关条目

浏览全部模组