Files
ngzz-mc/internal/inventory/inventory_test.go
2026-09-19 14:21:08 +08:00

156 lines
4.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package inventory
import (
"path/filepath"
"testing"
"mc/internal/item"
)
// loadItemReg 加载物品注册表。
func loadItemReg(t *testing.T) *item.Registry {
t.Helper()
r, err := item.Load(filepath.Join("..", "..", "assets", "config", "items.json"))
if err != nil {
t.Fatalf("加载物品注册表失败: %v", err)
}
return r
}
// TestMerge 验证合并规则(物品与背包.md §3 规则表)。
func TestMerge(t *testing.T) {
reg := loadItemReg(t)
inv := New(reg)
// 放入 30 个木板 → 合并到 34 个
rem := inv.Add(item.Stack{Name: "oak_planks", Count: 30})
if !rem.Empty() {
t.Fatal("30 个木板应全部放入")
}
rem = inv.Add(item.Stack{Name: "oak_planks", Count: 34})
if !rem.Empty() {
t.Fatal("34 个木板应合并入同一槽")
}
// 64 上限:再放 10 应进入新槽(槽 0 已满 64)
rem = inv.Add(item.Stack{Name: "oak_planks", Count: 10})
if !rem.Empty() {
t.Fatalf("剩余期望空,实际 %d", rem.Count)
}
if inv.Slots[1].Name != "oak_planks" || inv.Slots[1].Count != 10 {
t.Fatalf("槽 1 期望 10 个木板,实际 %+v", inv.Slots[1])
}
}
// TestRemove 验证取出物品。
func TestRemove(t *testing.T) {
reg := loadItemReg(t)
inv := New(reg)
inv.Add(item.Stack{Name: "stick", Count: 16})
if !inv.Remove("stick", 5) {
t.Fatal("应能取出 5 个")
}
if inv.Remove("stick", 20) {
t.Fatal("不足 20 个不应成功")
}
if !inv.Remove("stick", 11) {
t.Fatal("应能取出剩余 11 个")
}
}
// TestSelected 验证选中槽。
func TestSelected(t *testing.T) {
reg := loadItemReg(t)
inv := New(reg)
inv.Slots[3] = item.Stack{Name: "torch", Count: 8}
inv.Selected = 3
if s := inv.SelectedStack(); s.Name != "torch" || s.Count != 8 {
t.Fatalf("选中槽异常: %+v", s)
}
}
func TestCanPlaceArmor(t *testing.T) {
reg := loadItemReg(t)
planks := item.Stack{Name: "oak_planks", Count: 1}
helm := item.Stack{Name: "iron_helmet", Count: 1}
if CanPlace(reg, SlotHelmet, planks) {
t.Fatal("盔甲槽应拒收木板")
}
if !CanPlace(reg, SlotHelmet, helm) {
t.Fatal("头盔槽应接收铁头盔")
}
if CanPlace(reg, SlotChest, helm) {
t.Fatal("胸甲槽应拒收头盔")
}
if !CanPlace(reg, SlotOffhand, item.Stack{Name: "shield", Count: 1}) {
t.Fatal("副手应接收盾")
}
if CanPlace(reg, SlotOffhand, planks) {
t.Fatal("副手应拒收木板")
}
}
func TestClickRightHalf(t *testing.T) {
slot := item.Stack{Name: "oak_planks", Count: 5}
ns, nh := ClickRight(slot, item.Stack{}, 64, true)
if nh.Count != 3 || ns.Count != 2 {
t.Fatalf("空手右键应拿一半向上取整:槽=%d 手=%d", ns.Count, nh.Count)
}
ns, nh = ClickRight(item.Stack{}, nh, 64, true)
if ns.Count != 1 || nh.Count != 2 {
t.Fatalf("手持右键应放 1 个:槽=%d 手=%d", ns.Count, nh.Count)
}
}
func TestShiftHotbarMain(t *testing.T) {
reg := loadItemReg(t)
inv := New(reg)
inv.Slots[0] = item.Stack{Name: "stick", Count: 8}
if !inv.ShiftFromInv(0) {
t.Fatal("热键栏 Shift 应移到主区")
}
if !inv.Slots[0].Empty() || inv.Slots[9].Name != "stick" || inv.Slots[9].Count != 8 {
t.Fatalf("应进入主区槽 9,实际 hot=%+v main=%+v", inv.Slots[0], inv.Slots[9])
}
}
func TestAddSkipsArmor(t *testing.T) {
reg := loadItemReg(t)
inv := New(reg)
for i := 0; i < StorageSize; i++ {
inv.Slots[i] = item.Stack{Name: "dirt", Count: 64}
}
rem := inv.Add(item.Stack{Name: "oak_planks", Count: 1})
if rem.Empty() {
t.Fatal("存储满时不应写入盔甲槽")
}
if !inv.Slots[SlotHelmet].Empty() {
t.Fatal("盔甲槽应保持空")
}
}
func TestSpreadEven(t *testing.T) {
reg := loadItemReg(t)
slots := []item.Stack{{}, {}, {}, {}, {}}
ptrs := []*item.Stack{&slots[0], &slots[1], &slots[2], &slots[3], &slots[4]}
held := SpreadEven(reg, item.Stack{Name: "oak_planks", Count: 5}, ptrs)
if !held.Empty() {
t.Fatalf("5 个应均分完,剩余 %+v", held)
}
for i, st := range slots {
if st.Count != 1 {
t.Fatalf("槽 %d 应各 1,实际 %+v", i, st)
}
}
}
func TestGather(t *testing.T) {
reg := loadItemReg(t)
inv := New(reg)
inv.Slots[0] = item.Stack{Name: "stick", Count: 10}
inv.Slots[9] = item.Stack{Name: "stick", Count: 20}
held := inv.GatherStorage(item.Stack{}, "stick")
if held.Count != 30 {
t.Fatalf("应聚 30 棍,实际 %d", held.Count)
}
}