物品整理器

物品整理器

从游戏用户界面重建你的创意库存和标签页,并策划玩家能够获得的内容。

🗂️ 物品整理器

在游戏内重建你的创造模式物品栏。

整理玩家可以获得的物品——无需打开任何配置文件。

Minecraft 1.20.1 Forge Java 17

Client and Server MIT

无必要前置依赖。


❓ 问题所在

安装 150 个模组后,创造模式物品栏就变得难以使用。

十五页的标签页。物品按制造者而非种类分组。其中一半是你从未想加入整合包的东西。

针对整个标签页的优秀工具已经存在——Creative Tab Organizer 可以在创造模式界面中重新排序和隐藏标签页,MoreCreativeTabs 可以通过 JSON 组合新的标签页。这两个都很值得拥有。

但整合包的整理并非以标签页为粒度进行的,而是逐物品进行:

  • 这个小工具有些埋没在模组的标签页里,没人会去那里找——它应该属于工具类
  • 这是整合包里第四种铜矿石——其中三种根本不应该存在

这两个决定都不是标签页级别的决定。而且没有现成的工具可以移动单个物品,或是在创造模式之外对其做任何处理。

这个想法并不新鲜。CreativeTabsTweaker 在 1.12.2 时代就做到了——移除标签页、添加你自己的标签页、在它们之间移动物品——通过手动编写的 JSON 文件实现。但它从未移植到现代版本,因为现代版本中创造模式标签页已变为生成内容,而不是每个物品上的可变字段。

物品整理器重新拾起这个想法,将其带到 1.20.1,将手写 JSON 替换为两个鼠标手势——并让移除操作在创造模式之外真正生效。

🖱️ 这正是物品整理器填补的空白。

通过两个鼠标手势将任何物品移动到任何标签页——并让移除操作在生存模式、JEI、EMI、你的服务器上真正生效。


✨ 功能特性

🖱️ 在游戏中重组创造模式标签页

手势 结果
右键单击标签页标题 将此标签页的内容移动到…
Shift + 右键单击物品 将此物品移动到…

两者都会打开同一个选择器:一个包含所有创造模式标签页(原版和模组)的可滚动列表,带有一个实时搜索框。

这种设计是经过深思熟虑的。 当有十五页标签时,拖放操作在物理上是不可能的:拖动时你看不到目标位置。而输入三个字母只需一秒钟。

✅ 更改即时生效——标签页会原地重建,你停留在当前的界面上。无需重载,无需重新加入。 ✅ 规则会写入一个整洁、排序的 JSON 文件,你可以随整合包一起分发。 ✅ 清空的标签页会消失——将某个模组的整个标签页移走后,其空的标题栏不再占用空间;页面会自动重新计数。


🙈 隐藏层级

移除物品——同时保留你的主控钥匙

将物品或整个标签页发送到隐藏,它就会从你的整合包中消失:

  • ❌ 从所有创造模式标签页、JEI 和 EMI 中消失
  • ❌ 配方被禁用,生存模式下无法获取——物品栏被清除,拾取被阻止,掉落的物品会溶解,使用和攻击被阻止

……但对你除外。 一个带有屏障图标的标签页,仅在创造模式下且拥有权限等级 2+ 时可见,仍然存放着所有隐藏物品——这样管理员可以取出一个并正常使用:测试方块、查看提示、调试配方。

⚠️ 管理员不能做的是将它放回世界中。

扔出的物品会溶解 · 方块放置会被拒绝 · 打开容器时会被清除 隐藏物品只存在于创造模式管理员的物品栏中,其他地方不存在。 没有泄漏途径。没有意外赠予。没有重复物品溜进生存模式。


🩹 批量隐藏,再拯救例外

现实中的工作流程,全程支持:

1. 一个模组添加了一个包含 300 个物品的标签页,而你只想要其中三个 → 右键单击其标题 → 隐藏。       每个物品都会被单独隐藏,因此规则文件保持明确且可读。

2. 打开隐藏标签页 → Shift + 右键单击那三个要保留的物品 → 将每个发送到你选择的分类。

3. 右键单击隐藏标签页标题 → 你隐藏的所有物品,按它们来源的标签页分组,并带有一键恢复整个分组的功能。

改变主意了,想撤销某个之前移动的标签页? 右键单击目标标签页:传入的规则会列在选择器顶部,每条规则都有一个 ✕ 可以取消。指向你后来移除的模组的规则也会出现在那里,并且可以用同样的方式清理。


⛔ 黑名单

彻底根除

第二个更严厉的层级——支持正则表达式:

"blacklisted": [
  "somemod:broken_item",
  "!somemod:.*_deprecated"
]

被列入黑名单的物品会为所有人(包括管理员)抹除。 没有标签页。没有配方查看器。没有配方。没有物品栏。没有例外。 适用于那些根本不应该存在的物品。


🔗 配方:连锁反应,已处理

隐藏一个物品会移除产出它的配方。 但消耗它的配方会保留——在 JEI/EMI 中可见,却无法合成。这些死分支就是这样让一个精心整理的整合包开始产生错误报告的。

两个可选的级别可以处理这个问题:

"removeRecipesUsingHidden": false,   // 同时移除消耗受限物品的配方

"cascadeRecipeRemoval":     false,   // 传播:没有配方的物品变得无法获取,
                                     // 因此使用它们的配方也随之移除

"cascadeAbortPercent":      33       // 安全阀——见下文

接受多种物品的原料(例如标签)只在所有替代品都受限制时才被视为损坏——不会因为你隐藏了一种奇异木材就误报 #planks。

📋 审计日志行

无论你启用了什么,模组都会向日志写入一份摘要:移除了多少配方,以及哪些物品最终完全没有配方。 在设置好规则后阅读一次。这是了解你的整理工作实际上对进度产生了什么影响的最快方式。


⚠️ 安全护栏

谨慎移除物品

内置了两个硬性限制——还有一个经验法则取决于你自己。

🛡️ 自然地形和基础物品不可隐藏

泥土、石头、沙子、原木、木板、树叶、沙砾、工作台——这个世界就是由它们构成的。 隐藏其中一个意味着玩家挖掘的每个方块都会掉落一个瞬间溶解的物品。

UI 会拒绝此操作并显示一条消息,如果你手动将其写入 JSON 也会被拒绝。 受保护集合基于标签且可编辑——protectedTags / protectedItems——并带有明确的 allowProtectedOverride 选项,供真正有意为之的作者使用。

🚨 级联带有安全阀

如果传播会移除游戏中所有配方的超过 cascadeAbortPercent 比例(默认为 33%),则完全中止。 模组会回退到直接移除,并记录一条错误日志指出问题所在。

一条倒霉的规则再也不能在线上服务器上悄无声息地摧毁整个整合包。

🌿 经验法则

限制合成树的枝叶,而非其主干。

装饰性变种、重复的矿石、过强的小工具——这些是安全的。 基础材料、燃料、常见原料——预计你配方书里的一半都会跟着消失。

如有疑问:先隐藏它,阅读审计日志行,如果数字让你吃惊,一键撤销即可。

💚 给担心的人的好消息

隐藏物品绝不会触碰世界中已经放置的方块。 只有物品形式受到影响——不会重写地形、不会编辑区块、不会删除任何人建筑中的任何东西。


🧩 为整合包而生

🔌 缺失模组 对你移除的模组的引用会被静默跳过——不会崩溃、不会刷错误——如果该模组回归则会重新激活
♻️ 热重载 更喜欢手动编辑 JSON?更改会在两秒内生效
🌱 Git 友好 格式美化、键值排序、差异稳定
🩺 配置损坏 一条警告、自动创建 .broken 备份,游戏照常启动

⚙️ 配置

规则 — config/itemsorganisator.json

由游戏内 UI 为你写入:

{
  "tabMoves":    { "somemod:somemod_tab": "minecraft:functional_blocks" },
  "itemMoves":   { "somemod:gadget": "minecraft:tools_and_utilities" },
  "hidden":      [ "somemod:op_item" ],
  "blacklisted": [ "brokenmod:ghost_item", "!brokenmod:.*_wip" ],

  "removeRecipesUsingHidden": false,
  "cascadeRecipeRemoval":     false,
  "cascadeAbortPercent":      33,
  "allowProtectedOverride":   false,

  "protectedTags":  [ "minecraft:dirt", "minecraft:planks", "minecraft:logs", "…" ],
  "protectedItems": [ "minecraft:gravel", "minecraft:crafting_table", "…" ]
}

优先级,从高到低:

blacklisted → hidden → itemMoves → tabMoves → 自然放置

控制 — config/itemsorganisator-controls.toml

鼠标按键、修饰键、通知提示、隐藏标签页位置——以及一个主开关,editingEnabled。

🔒 以 editingEnabled = false 发布你的整合包

玩家可以获得整理好的物品栏,但没有重写它的能力。

因为这是一个普通的 Forge 配置规范,Configured 可以自动将其渲染为游戏内设置界面,无需额外设置——和下面的所有集成一样,完全可选。

将这两个文件随整合包一起分发,服务端和客户端都要有。 客户端 UI 读取它们;服务端强制执行它们。玩家编辑本地副本只会改变他们看到的,绝不会改变他们能获得的。


🔍 诚实的范围说明

1.x 版本未覆盖的内容:

  • 村民和流浪商人的交易  — 购买的物品会在一秒内被清除,但交易仍然会显示
  • /give  — 同样的一秒清除
  • 生成的结构箱子内的战利品  — 打开容器时会被清除
  • 末影箱  — 打开时会被清除,与任何其他容器一样

原版物品栏和打开的容器菜单已被完全处理。

自 1.8.0 起,嵌套和模组物品栏也被处理:

  • Curios 饰品栏  — 与玩家物品栏一起扫描,同样的创造模式豁免
  • 背包和便携容器  — 任何暴露标准 Forge ITEM_HANDLER 能力的物品,这涵盖了 Sophisticated Backpacks、TACZ 装备包等大多数模组,无需单独修补
  • 潜影盒  — 直接从物品 NBT 中读取,其内容实际存储在那里

嵌套会深入一层——包中之包。容器本身永远不会被摧毁,只会移除其中的受限物品。玩家携带的容器每五秒扫描一次,而不是每秒一次:埋在背包深处的物品无法立即使用,而且深入检查容器比扫一遍平面物品栏开销更大。


🤝 兼容性

模组 增加了什么
JEI 隐藏和列入黑名单的物品会实时从索引中移除
EMI 同样,通过原生 EMI 插件实现——EMI 构建自己的索引,所以这是一个独立的集成,而非 JEI 的副作用
Reliable EMI (原 EMI++) 其基于创造标签页的 EMI 内部视图会跟随你的重组,包括清空的标签页。两者结合使用,你整理好的分类就会成为玩家浏览的对象,而不仅仅是创造模式下的管理员
ModernFix 完全兼容——其创造标签页记忆化已被处理(见技术说明)
Configured 自动提供游戏内设置界面
Creative Tab Organizer 互补而非竞争——它重新排序和隐藏整个标签页,本模组移动单个物品并强制执行移除。如果你喜欢,可以两者同时使用
无任何模组 一切功能照常工作

每个集成都是可选的,并独立进行防护:缺失的模组永远不会被类加载,失败的集成会安静地降级,而不会破坏你的游戏。


🔧 技术说明

面向开发者——如果你只想要模组本身,可以跳过此节

插入与移除

插入使用 Forge 的 BuildCreativeModeTabContentsEvent。 移除在 1.20.1 中没有 API,因此一个 mixin 在 CreativeModeTab#buildContents 的 TAIL 处过滤 displayItems / displayItemsSearchTab,通过 @Accessor 接口访问。

本模组中没有任何 @Shadow——注解处理器会从 refmap 中省略阴影,从而导致 mixin 在开发环境中正常工作但在生产环境中崩溃。访问器和调用器没有这种失败模式。

实时重建与 ModernFix

原版会在 ItemDisplayParameters 未改变时短路 CreativeModeTabs#tryRebuildTabContents,因此仅编辑规则永远不会触发重建——必须首先使静态的 CACHED_PARAMETERS 失效。

当安装了 ModernFix 时,这还不够。 它的 perf.memoize_creative_tab_build 模块为每个标签页包装了 buildContents,并将结果记忆化在一个注入的 mfix$oldParameters 字段中。当参数相同时,它会返回记忆化的内容,而实际的构建——包括每个模组的标签页内容事件——永远不会运行。

物品整理器会在每次重建前通过反射清除该字段(一次性查找,当 ModernFix 不存在或模块关闭时为空操作),然后同步调用原版重建,以便界面根据新的集合重新初始化。

如果你要编写任何在 1.20.1 上于运行时编辑创造标签页的代码,这个交互会让你浪费一个下午。

配方查看器刷新延迟执行

EMI 异步重载,并在完成时重建屏幕组件;在物品栏打开时触发它会在渲染过程中修改组件列表——导致 ConcurrentModificationException。

因此,EMI 重载和 Reliable EMI 的标签页列表刷新都会被排队,并在没有屏幕打开时于客户端 tick 时刷新——这也会将整个编辑会话批量处理为一次重载。

标签页排序与空标签页

创造模式界面从 Forge 的 CreativeModeTabRegistry#getSortedCreativeModeTabs 构建其页面,即模组加载顺序。隐藏标签页会在返回时被移动到该列表的末尾(mixin,remap = false,可配置)。

空标签页无需特殊处理:原版的 CreativeModeTab#shouldDisplay 已经会过滤空的 CATEGORY 标签页,Forge 会在 CreativeModeInventoryScreen#init 中重新计算页面。清空集合就足够了。

服务端强制执行与性能

强制执行是事件驱动的——拾取、掉落(EntityJoinLevelEvent)、交互、攻击、打开容器——外加一个注入到 RecipeManager#apply 尾部的配方过滤器,以及一个每秒运行一次而非每 tick 运行一次的物品栏扫描。

查询是基于注册表身份的 HashSet 成员测试。黑名单正则表达式在每次配置加载时编译一次,并解析为预先计算的物品集合——游戏过程中绝不进行求值。 每帧都不运行任何东西。

配方移除是在加载时进行的,因此在会话中隐藏物品会使其配方保留到 /reload 或重启为止。JEI 和 EMI 的移除是实时的;取消隐藏会在下次重载时恢复它们。

构建

编译针对 JEI 15.20.0.106 和 EMI 1.1.24(compileOnly)、Forge 47.3.0、Java 17、官方 mappings。


🙏 致谢

此概念源自 CreativeTabsTweaker,作者 MeowSkyKung(Forge 1.12.2)——第一个允许整合包作者移除标签页、创建新标签页并在其间移动物品的模组。其配置布局启发了本模组配置的形态。但其代码无法复用:1.12 的方法依赖于每个物品上的可变创造标签页字段,而现代版本已不再拥有该字段。

Creative Tab Organizer 由 Ziver1246 制作,以及 MoreCreativeTabs 覆盖了现代版本上的标签页级组织,与本模组搭配良好。


📦 源代码

完整源代码托管在 GitHub 上,遵循 MIT 许可证——可以阅读、构建、分发,或提交 Issue。

github.com/doublescotch/items-organisator

分支与目标版本对应:1.20.1/forge。所有依赖都从 Maven 解析,因此克隆后只需 gradlew build 即可构建——无需手动下载任何东西。JEI 来自 BlameJared Maven,EMI 和 Curios 来自 Modrinth Maven。


MIT · 作者 Hell_Kaiser

欢迎提交 Issue、建议和 Pull Request。