搜索附近库存物品
基本信息
| 属性 | 值 |
|---|---|
| 默认按键 | T |
| 内部 ID | gui.findit.find_item |
| 类别 | nei.options.keys.gui.findit |
| 语言条目 | nei.options.keys.gui.findit.find_item = “Search For Item In Nearby Inventories”(en_US)/ “搜索附近库存中的物品”(zh_CN) |
| 注册类 | com.gtnh.findit.service.itemfinder.ClientItemFindService 构造器 |
| 触发类 | com.gtnh.findit.service.itemfinder.ClientItemFindService.ItemFindInputHandler(继承 AbstractStackFinder) |
| 容器监听 | NEI GuiContainerManager.addInputHandler(...) |
功能
按下 T 键触发 NEI IContainerInputHandler.lastKeyTyped 钩子,悬停目标 ItemStack 并向服务器发送 FindItemRequest 消息。
服务器 ItemFindService.handleRequest 收到请求后:
- 通过
SearchCooldownService.checkSearchCooldown检查冷却; - 调用
WorldUtils.getTileEntitiesAround(player, FindItConfig.SEARCH_RADIUS)取出±SearchRadius立方体内的所有 TileEntity; - 对每个 TileEntity 调用
FindItemRequest.isTileSatisfies(player, tileEntity),依次遍历FindIt.pluginsList里每个IStackFilterProvider,调用provider.getFilter(player, tileEntity)取得IStackFilter并filter.matches(request);任一 provider 匹配即加入命中ChunkPosition列表; - 列表大小达到
FindItConfig.MAX_RESPONSE_SIZE时停止; - 通过
FindItNetwork.CHANNEL.sendTo(...)把BlockFoundResponse(positions)与ItemFoundResponse(targetStack)发回客户端。
触发与限制
| 触发条件 | 行为 |
|---|---|
客户端在 NEI 容器内按 T 键悬停 ItemStack |
发送 FindItemRequest(stack) 给服务器;命中时同时高亮地面 EntityItem(紫色描边)与当前 GUI 中的非玩家槽位(贴图覆盖) |
命中后存在非空地面 EntityItem 列表(SearchItemsOnGround 开启) |
客户端 EntityHighlighter.highlightEntities 用 GL11.glColor4f(0.75f, 0.0f, 1.0f, 1.0f)(紫色)画 FxHelper.renderEntityOutline 描边 |
| ExtraUtilities 已加载 | ItemFindInputHandler.getKeyBindId() 返回 gui.xu_ping,复用 ExtraUtilities 的 T 键绑定;同时 NEIEventListener.onNEIConfigsLoaded 把 com.rwtema.extrautils.nei.ping.NEIPing 输入处理器从 GuiContainerManager.inputHandlers 中移除,避免与 findit 冲突 |
服务端 GregTech 已加载但 SEARCH_IN_GT_PIPES 未开启,且 TileEntity 是 BaseMetaPipeEntity |
isTileSatisfies 直接返回 false(不搜索 GT 管道内容) |
服务端 EnderIO 已加载但 SEARCH_IN_ENDERIO_CONDUITS 未开启,且 TileEntity 是 TileConduitBundle |
isTileSatisfies 直接返回 false(不搜索 EnderIO 导管内容) |
ITEM_HIGHLIGHTING_EMPTY_ITEMSTACKS 为 false,且 stack stackSize == 0 |
isStackSatisfies 直接返回 false(不视为命中) |
| 服务端处于冷却期 | 直接返回,不发送响应 |
| 目标 ItemStack 为 null | FindItemRequest.Handler.onMessage 守卫忽略 |
高亮渲染
SlotHighlighter(GUI 槽位贴图覆盖)
com.gtnh.findit.fx.SlotHighlighter 实现 NEI IContainerDrawHandler.renderSlotUnderlay,对每个 gui.findit.getDock(...) 的 Slot 在原槽位上画 textures/gui/slot_highlight.png(0.5625×0.5625 贴图,UV (0,0)–(18/32, 18/32)),颜色由 FindItConfig.ITEM_HIGHLIGHTING_COLOR 配置(ARGB 16 进制字符串,默认 FFFF8726)。
每客户端 tick 重算高亮集合:
- 仅在
GuiContainer当前打开时计算; - 遍历
gui.inventorySlots.inventorySlots,跳过slot.inventory instanceof InventoryPlayer(不标玩家背包); - 命中数达到 256 时停止;
- 高亮有效期由
System.currentTimeMillis() + FindItConfig.ITEM_HIGHLIGHTING_DURATION * 1000L控制(默认 10 秒)。
EntityHighlighter(地面物品紫色描边)
com.gtnh.findit.fx.EntityHighlighter 在 RenderWorldLastEvent 里对 entityIds 列表逐个画 FxHelper.renderEntityOutline,EntityItem 时附加自旋/上下浮动(shouldBob() + hoverStart 三角函数 + age 旋转),scale=1.2f。
闪烁:((time / 500) & 1) == 0 时不画(一秒闪三次的开/关切换)。
时长:FindItConfig.ITEM_HIGHLIGHTING_DURATION 秒(默认 10 秒),到期后 entityIds.clear()。
数值
| 数值 | 默认 | 来源 |
|---|---|---|
| 默认按键 | T(Keyboard.KEY_T,仅当 ExtraUtilities 未加载) |
ClientItemFindService 构造器 |
| 搜索半径 | 16(chebyshev/立方体) |
FindItConfig.SEARCH_RADIUS |
| 服务端冷却 | 10 tick |
FindItConfig.SEARCH_COOLDOWN |
| 最大响应数 | 20(服务端 TileEntity 与客户端 EntityItem 共用) |
FindItConfig.MAX_RESPONSE_SIZE |
| 高亮时长 | 10 秒(GUI 槽位 + 地面物品) |
FindItConfig.ITEM_HIGHLIGHTING_DURATION |
| 高亮颜色 | 0xFFFF8726(橙红色 ARGB) |
FindItConfig.ITEM_HIGHLIGHTING_COLOR |
| 单 tick 最大高亮槽位数 | 256 |
ClientItemFindService.TickListener.onClientPostTick |
第三方 mod 集成
按 FindIt.preInit 的注册顺序(共 8 个 provider):
| 集成 mod | 触发条件 | 行为 |
|---|---|---|
| Minecraft(默认) | 始终 | IInventory 逐槽位 + IFluidTank.getFluid() + IFluidHandler.getTankInfo(ForgeDirection.UNKNOWN) 流体;物品侧 StackInfo.getFluid(stack) 转 FluidStack + StackInfo.equalItemAndNBT(..., true) |
| Forestry | Loader.isModLoaded("Forestry") |
ItemBackpack → ItemInventoryBackpack(player, backpack.getBackpackSize(), stack) 包成 InventoryStackFilter |
| AdventureBackpack | Loader.isModLoaded("adventurebackpack") |
IInventoryBackpack 槽位 + getTanksArray() 流体;物品侧 InventoryBackpack(stack) |
| ProjectRed Exploration | `Loader.isModLoaded("ProjRed | Exploration")` |
| DraconicEvolution | Loader.isModLoaded("DraconicEvolution") |
TilePlacedItem.getStack() 直接栈匹配 |
| Backpack (eydamos) | Loader.isModLoaded("Backpack") |
ItemBackpack.getInventory(stack, player) |
| Thaumcraft | Loader.isModLoaded("Thaumcraft") |
IAspectContainer + IEssentiaContainerItem.getAspects(stack) Aspect 匹配;额外兼容 aspectrecipeindex 与 thaumcraftneiplugin 的 ItemAspect |
| GregTech | Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi") |
ICoverable.hasCoverAtSide/getCoverItemAtSide 比对 GT 盖板;CoverChest.getItems() 逐槽位 |
| ExtraUtilities | Loader.isModLoaded("ExtraUtilities") |
复用其 gui.xu_ping 热键并移除 NEIPing 输入处理器(不增加 provider) |
相关条目
- 物品搜索服务 - 服务端/客户端 ItemFindService 实现细节与
IStackFilter体系 - FindItConfig - 所有可调开关与默认值
- 搜索冷却服务 - 每玩家 tick 计数器冷却
- 搜索附近方块 - 配对使用:方块型 vs 物品型搜索