From eef5ddaa94f8cff6010d092c30fed53d2be01524 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Wed, 17 Jun 2026 17:34:40 -0400 Subject: feat: began implementing smithing, ground item display fixes. --- internal/game/cmd_look.go | 125 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 38 deletions(-) (limited to 'internal/game/cmd_look.go') diff --git a/internal/game/cmd_look.go b/internal/game/cmd_look.go index 8cadfd3..77c8776 100644 --- a/internal/game/cmd_look.go +++ b/internal/game/cmd_look.go @@ -214,27 +214,24 @@ func (g *Game) doLook(sess *net.Session) { ground := g.World.GroundItemsDetailed(p.RoomID) if len(ground) > 0 { - sort.Slice(ground, func(i, j int) bool { - ni := ground[i].ItemID - if def, err := g.ItemStore.Load(ground[i].ItemID); err == nil { - ni = def.Name - } - nj := ground[j].ItemID - if def, err := g.ItemStore.Load(ground[j].ItemID); err == nil { - nj = def.Name - } - return strings.ToLower(ni) < strings.ToLower(nj) - }) + showDespawn := p.OptionBool("despawn") + showReserve := p.OptionBool("reserve") - sess.WriteLine("") - sess.WriteLine("On the ground:") + type displayLine struct { + name string + quantity int + colorName string + annotation string + } - type groundLine struct { - prefix string - reserved string + type groupKey struct { + itemID string + despawnTimer int } - var lines []groundLine - maxPrefix := 0 + + var lines []displayLine + groups := make(map[groupKey]*displayLine) + var groupOrder []groupKey for _, info := range ground { def, err := g.ItemStore.Load(info.ItemID) @@ -243,37 +240,89 @@ func (g *Game) doLook(sess *net.Session) { name = def.Name } coloredName := g.itemColorize(sess, def, name) - prefix := "" - if info.Quantity > 1 { - prefix = fmt.Sprintf(" %d x %s", info.Quantity, coloredName) - } else { - prefix = fmt.Sprintf(" %s", coloredName) - } - if visibleLen(prefix) > maxPrefix { - maxPrefix = visibleLen(prefix) - } - var parts []string + if info.ReservedFor != "" { - if p.OptionBool("reserve") { + var parts []string + if showReserve { parts = append(parts, fmt.Sprintf("reserved for %s %dt", info.ReservedFor, info.ReserveTimer)) } else { parts = append(parts, "reserved") } + if showDespawn && !info.IsSpawn { + parts = append(parts, fmt.Sprintf("despawns %dt", info.DespawnTimer)) + } + annotation := "" + if len(parts) > 0 { + annotation = fmt.Sprintf(" (%s)", strings.Join(parts, ", ")) + } + lines = append(lines, displayLine{ + name: name, + quantity: info.Quantity, + colorName: coloredName, + annotation: annotation, + }) + continue + } + + timerKey := -1 + if showDespawn && !info.IsSpawn { + timerKey = info.DespawnTimer + } + key := groupKey{itemID: info.ItemID, despawnTimer: timerKey} + + if existing, ok := groups[key]; ok { + existing.quantity += info.Quantity + } else { + annotation := "" + if showDespawn && !info.IsSpawn { + annotation = fmt.Sprintf(" (despawns %dt)", info.DespawnTimer) + } + dl := &displayLine{ + name: name, + quantity: info.Quantity, + colorName: coloredName, + annotation: annotation, + } + groups[key] = dl + groupOrder = append(groupOrder, key) } - if p.OptionBool("despawn") && !info.IsSpawn { - parts = append(parts, fmt.Sprintf("despawns %dt", info.DespawnTimer)) + } + + for _, key := range groupOrder { + lines = append(lines, *groups[key]) + } + + sort.Slice(lines, func(i, j int) bool { + return strings.ToLower(lines[i].name) < strings.ToLower(lines[j].name) + }) + + sess.WriteLine("") + sess.WriteLine("On the ground:") + + type fmtLine struct { + prefix string + annotation string + } + var fmtLines []fmtLine + maxPrefix := 0 + + for _, dl := range lines { + prefix := "" + if dl.quantity > 1 { + prefix = fmt.Sprintf(" %d x %s", dl.quantity, dl.colorName) + } else { + prefix = fmt.Sprintf(" %s", dl.colorName) } - reserved := "" - if len(parts) > 0 { - reserved = fmt.Sprintf(" (%s)", strings.Join(parts, ", ")) + if visibleLen(prefix) > maxPrefix { + maxPrefix = visibleLen(prefix) } - lines = append(lines, groundLine{prefix, reserved}) + fmtLines = append(fmtLines, fmtLine{prefix, dl.annotation}) } - for _, l := range lines { - if l.reserved != "" { + for _, l := range fmtLines { + if l.annotation != "" { pad := maxPrefix + 1 + (len(l.prefix) - visibleLen(l.prefix)) - sess.WriteLine(fmt.Sprintf("%-*s%s", pad, l.prefix, l.reserved)) + sess.WriteLine(fmt.Sprintf("%-*s%s", pad, l.prefix, l.annotation)) } else { sess.WriteLine(l.prefix) } -- cgit v1.2.3