package playerdb import ( "bytes" "github.com/df-mc/dragonfly/server/internal/nbtconv" "github.com/df-mc/dragonfly/server/item" "github.com/sandertv/gophertunnel/minecraft/nbt" ) // InventoryData is a struct that contains all data of the player inventories. type InventoryData struct { // Items contains all the items in the player's main inventory. // This excludes armour and offhand. Items []item.Stack // Boots, Leggings, Chestplate, Helmet are armour pieces that belong to the slot corresponding to the name. Boots item.Stack Leggings item.Stack Chestplate item.Stack Helmet item.Stack // OffHand is what the player is carrying in their non-main hand, like a shield or arrows. OffHand item.Stack // MainHandSlot saves the slot in the hotbar that the player is currently switched to. // Should be between 0-8. MainHandSlot uint32 } func invToData(data InventoryData) jsonInventoryData { d := jsonInventoryData{ MainHandSlot: data.MainHandSlot, OffHand: encodeItem(data.OffHand), } d.Items = encodeItems(data.Items) d.Boots = encodeItem(data.Boots) d.Leggings = encodeItem(data.Leggings) d.Chestplate = encodeItem(data.Chestplate) d.Helmet = encodeItem(data.Helmet) return d } func dataToInv(data jsonInventoryData) InventoryData { d := InventoryData{ MainHandSlot: data.MainHandSlot, OffHand: decodeItem(data.OffHand), Items: make([]item.Stack, 36), } decodeItems(data.Items, d.Items) d.Boots = decodeItem(data.Boots) d.Leggings = decodeItem(data.Leggings) d.Chestplate = decodeItem(data.Chestplate) d.Helmet = decodeItem(data.Helmet) return d } func encodeItems(items []item.Stack) (encoded []jsonSlot) { encoded = make([]jsonSlot, 0, len(items)) for slot, i := range items { data := encodeItem(i) if data == nil { continue } encoded = append(encoded, jsonSlot{Slot: slot, Item: data}) } return } func decodeItems(encoded []jsonSlot, items []item.Stack) { for _, i := range encoded { items[i.Slot] = decodeItem(i.Item) } } func encodeItem(item item.Stack) []byte { if item.Empty() { return nil } var b bytes.Buffer itemNBT := nbtconv.WriteItem(item, true) encoder := nbt.NewEncoderWithEncoding(&b, nbt.LittleEndian) err := encoder.Encode(itemNBT) if err != nil { return nil } return b.Bytes() } func decodeItem(data []byte) item.Stack { var itemNBT map[string]any decoder := nbt.NewDecoderWithEncoding(bytes.NewBuffer(data), nbt.LittleEndian) err := decoder.Decode(&itemNBT) if err != nil { return item.Stack{} } return nbtconv.Item(itemNBT, nil) }