大猩猩宝箱模组

大猩猩宝箱模组

Valheim中箱子的便捷模组:更大的堆叠(1000),从附近的箱子制作,自动堆叠到所有箱子(按J键),以及收藏物品栏物品(Alt+点击)。

Valheim 的箱子体验优化,分为四部分:

  1. 从箱子中制作。 使用周围箱子内的物品进行制作、升级和建造,无需先将物品搬运到你的物品栏中。
  2. 超大箱子堆叠。 一个箱子槽位可容纳远超原版上限的数量,默认 1000,因此装满木头的箱子只占一个槽位而非二十个。你自己的物品栏仍保持原版上限。
  3. 快速堆叠。J 键将物品栏中匹配的物品推入范围内的箱子。J 键在 Valheim 中是空闲的:V 是自动拾取,G 打开快捷栏径向菜单。
  4. 收藏。Alt + 左键 标记一个堆叠,自动移动会将其忽略,包括上述的快速堆叠和箱子自身的堆叠按钮。

客户端和专用服务器均可运行。

构建所针对的游戏版本

项目
游戏版本 1.0.7
Steam 构建 25185596
引擎 Unity 6000.0.75f1,Mono 后端
游戏代码 valheim_Data/Managed/assembly_valheim.dll

由于后端是 Mono 而非 IL2CPP,常规的模组路径仍然适用:BepInEx 5 加 Harmony,在内存中打补丁。不修改任何游戏文件。

安装

  1. 为 Valheim 安装 BepInEx 5,即 denikson-BepInExPack_Valheim 包。启动游戏一次以创建其文件夹。
  2. GorilaChestMod.dll 复制到 Valheim/BepInEx/plugins/GorilaChestMod/,或将 -nexus.zip 发布包解压到游戏文件夹上。
  3. 启动游戏。BepInEx/LogOutput.log 应包含一行 GorilaChestMod 2.4.0 loaded

使用 r2modman 或 Thunderstore Mod Manager 时,使用 Import local mod 并选择 -thunderstore.zip 发布包。不要将模组管理器与手动安装在游戏根目录的 BepInEx 混用,这是模组重复加载或完全不加载的经典原因。

在专用服务器上

[url=https://github.com/trentinidev/GorilaChestMod#on-a-dedicated-server][/url]

面向服务器运营者的完整分步指南(Windows、Linux 和租用面板):docs/server-install.md

简要版本与上述相同,放入服务器的 BepInEx/plugins,并且每位玩家也都需要安装。服务器端存在有两个原因:

  • 将箱子加载到内存的服务器决定其堆叠可以有多大。原版服务器会将超大堆叠钳制回原版上限,并在下次写入该箱子时销毁多余部分。
  • 服务器在每位客户端连接时将其箱子堆叠设置发送给客户端,因此整个会话对上限达成一致。

从箱子中制作和快速堆叠完全在玩家自己的机器上决定,因此这两项在原版服务器上仍可正常工作。

配置

BepInEx/config/dev.trentini.gorilachestmod.cfg 在首次启动时写入,可在游戏关闭时编辑。

选项 默认值 作用
Craft from chests Enabled true 在制作、升级和建造时计入附近的箱子。
Craft from chests Range 20 半径,单位为米。快速堆叠使用相同半径。
Craft from chests UseForBuilding true 也从箱子中支付锤子、锄头和耕耘机的费用。
Craft from chests IncludeVehicleContainers true 包含推车和船上的容器。
Chest stacks Enabled true 允许箱子内的超大堆叠。
Chest stacks ChestStackSize 1000 一个箱子槽位可容纳的数量,最高 10000。服务器的值优先。
Chest stacks ShrinkStackText true 数字变长时保持槽位标签可读,1000 显示为 1k。
Quick stack Enabled true 启用快速堆叠热键。
Quick stack SkipHotbar true 不动快捷栏那一行。
Quick stack Hotkey J 快速堆叠的热键,物品栏打开或关闭时均可。
Quick stack HotkeyNeedsInventory false 要求物品栏打开才能使用热键。
Favorites Enabled true 允许将堆叠标记为不可触碰。
Favorites Modifier LeftAlt 按住此键并左键点击堆叠以标记。左右两侧的键均可。
Favorites ShowMarker true 在标记的槽位上绘制一颗星。
Favorites Announce true 标记或取消标记堆叠时打印一行提示。
Debug Verbose false 记录每次取出、移动和已打补丁的调用。

当你连接到安装了该模组的服务器时,只要保持连接,该服务器在 Chest stacks 下的 EnabledChestStackSize 就会替换你的本地值。其他所有设置保持个人化。

哪些箱子会被计入

只有当箱子通过与你尝试打开它时游戏所应用的相同规则时,才会被使用:

  • 它位于配置的半径内;
  • 隐私为 Public,或为 Private 且你是该部件的创建者,因此团队箱子会像原版一样被排除在外;
  • 如果箱子检查守卫石,你需要拥有该守护区域的访问权限;
  • 没有其他人打开它,正被其他玩家使用的箱子会被跳过。

在取走任何东西之前,模组通过 ZNetView.ClaimOwnership 声明箱子的网络所有权,这是将物品栏写回 ZDO 的授权方式。这与游戏用于“全部拿走”的机制相同。

工作原理

从箱子中制作

[url=https://github.com/trentinidev/GorilaChestMod#craft-from-chests][/url]

游戏方法直接从 m_inventory 字段读取玩家物品栏,没有任何扩展点。模组不会向你的背包注入虚假物品,而是使用转译器仅重写这些方法内的物品栏调用。实例调用已经将 this 作为其第一个堆叠参数,因此第一个参数为 Inventory 的静态方法可直接替换,而方法体的其余部分保持不变。

游戏方法 替换的调用 原因
Player.HaveRequirementItems CountItems 解锁配方和制作按钮
Player.GetFirstRequiredItem CountItemsGetItem 单一材料的配方,如蜜酒和盛宴
Player.ConsumeResources RemoveItem 支付制作和放置部件的费用
Player.HaveRequirements(Piece) HaveItemCountItems 解锁建筑部件
InventoryGui.DoCrafting RemoveItem 支付单一材料
InventoryGui.SetupRequirement CountItems UI 中的拥有/需要数量

Container.Awake 注册每个生成的箱子,因此永远不需要 FindObjectsOfType 扫描,而 Player.UpdatePlacementHud.SetupPieceInfo 标记建造上下文,以便可以遵守 UseForBuilding

超大箱子堆叠

[url=https://github.com/trentinidev/GorilaChestMod#oversized-chest-stacks][/url]

堆叠上限是普通字段 ItemData.m_shared.m_maxStackSize,在 InventoryInventoryGrid 内的少数地方被读取。转译器将每次字段读取转换为一个调用,该调用还接收正在操作的物品栏,因此同一物品类型在箱子中返回 1000,在背包中返回原版的 50。

之后降低上限永远不会销毁任何东西:当保存的箱子被重建时,从磁盘读取的堆叠会为该单个物品提高上限,因此在较大设置下装满的箱子会保留其内容。它只是停止增长。方法列表在启动时从游戏自身的 IL 中发现,而非硬编码,并写入日志。

这一单一更改也涵盖了保存和加载:从保存的字节重建物品栏的 Inventory.AddItem 重载会按同一字段进行钳制,这就是为什么原版服务器或原版客户端否则会裁掉多余部分。

三道防护防止超大堆叠泄漏出箱子:

  • Inventory.AddItem(ItemData) 将对于目标来说过大的堆叠拆分到多个槽位,因此从箱子中按住 Shift 点击 1000 个木头会给你二十个原版堆叠。
  • 目标槽位的 Inventory.AddItem 只移动原版大小的部分并将该移动报告为部分完成,因此其余部分留在箱子中。
  • ItemDrop.DropItem 将超大堆叠拆分为多次掉落,因此被摧毁的箱子会散落普通堆叠而非一个不可能的巨大堆。

快速堆叠

[url=https://github.com/trentinidev/GorilaChestMod#quick-stack][/url]

热键在 InventoryGui.Update 中读取,并在物品栏关闭时工作,因此你可以站在箱子旁边按下它。当菜单、控制台、聊天或文本字段获得焦点时,以及玩家死亡时,它会暂停。刻意没有按钮:曾经有一个按钮位于物品栏旁边,却总是落在其他面板前面。物品只会移入已持有该物品的箱子,已装备和任务物品会被跳过,除非你另有说明,否则快捷栏会被跳过。

收藏

[url=https://github.com/trentinidev/GorilaChestMod#favorites][/url]

标记是物品自身自定义数据中的单个条目,即游戏已经与耐久度和品质一起序列化的字典。这无需任何簿记即带来三个好处:它随物品保存和加载,ItemData.Clone 会复制它,因此拆分堆叠会保留两半的标记,并且当你手动移动它时它会随堆叠一起移动。合并是游戏会丢失标记的唯一情况,因此目标槽位的 Inventory.AddItem 在任一侧有标记时会将其携带过去。

点击在 InventoryGui.OnSelectedItem 中被捕获:按住修饰键时点击会切换标记并被吞掉,否则原版照常运行。星星在启动时一次性绘制到纹理中,因为游戏 UI 没有星星可借用,并且同一精灵会被每个槽位复用。

箱子自身的堆叠按钮也会被遵守。它已经通过 Humanoid.IsItemEquiped 拒绝移动你已装备的物品,因此转译器将该调用指向一个对已标记堆叠也回答“是”的检查。

服务器端

[url=https://github.com/trentinidev/GorilaChestMod#server-side][/url]

该插件在 valheim_server.exe 以及 valheim.exe 中加载。在服务器上没有本地玩家,因此从箱子中制作和快速堆叠根本不会触发,而堆叠上限补丁会在服务器接触的每个箱子上发挥作用。

配置同步使用游戏自身网络层的两个路由 RPC:客户端在连接后请求一次,服务器以其箱子堆叠设置回应,服务器永远不会从客户端获取这些值。

已知限制

  • 移除模组会留下超大堆叠。 原版在加载箱子时会将堆叠钳制回其正常上限,多余部分会消失。在卸载前清空你的箱子,或降低 ChestStackSize 并让箱子稳定下来。没有安装模组的玩家打开装有超大堆叠的箱子也是如此。
  • 在 Valheim 中修理不消耗材料,因此那里无需处理。
  • 熔炉、窑和其他通过直接交互接收矿石或木材的站点不会从箱子中供给。制作、升级和建造则会。
  • 快速堆叠按钮由鼠标驱动,目前没有手柄绑定。
  • 其他玩家当时打开的箱子会被跳过,直到他们关闭它。