From 153acb7f644d755c45533b7c5311e3ffa47e8973 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 05:31:09 -0400 Subject: fix: harden engine across casino, economy, concurrency, security, and content --- internal/game/cmd_shop.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'internal/game/cmd_shop.go') diff --git a/internal/game/cmd_shop.go b/internal/game/cmd_shop.go index 7299ad3..f3211e0 100644 --- a/internal/game/cmd_shop.go +++ b/internal/game/cmd_shop.go @@ -366,8 +366,13 @@ func (g *Game) doShopSell(sess *net.Session, mob *world.MobInstance, input strin // shopInvCapacity reports how many of an item the player can still carry. func (g *Game) shopInvCapacity(p *player.Player, itemID string, def *item.ItemDef) int { if def != nil && def.Stackable { + quality, maxQuality := stackProps(def) for i := 0; i < 28; i++ { - if slot := p.InvSlot(i); slot != nil && slot.ItemID == itemID { + // Capacity must agree with giveShopItems: only a stack with the + // properties a fresh stack gets can absorb a purchase (see + // stackProps). Counting a differently qualified stack here would + // let the caller charge for items the delivery path cannot place. + if slot := p.InvSlot(i); slot != nil && slot.ItemID == itemID && slot.Quality == quality && slot.MaxQuality == maxQuality { return 1 << 30 } } @@ -383,8 +388,13 @@ func (g *Game) shopInvCapacity(p *player.Player, itemID string, def *item.ItemDe // possible. Callers must ensure capacity via shopInvCapacity first. func (g *Game) giveShopItems(p *player.Player, itemID string, qty int, def *item.ItemDef) { if def != nil && def.Stackable { + // Merge only into a stack with the properties this purchase would + // itself receive (stackProps/newInventorySlot), matching craft, + // harvest, ammo return and pickup: a differently qualified stack is + // not a merge target. + quality, maxQuality := stackProps(def) for i := 0; i < 28; i++ { - if slot := p.InvSlot(i); slot != nil && slot.ItemID == itemID { + if slot := p.InvSlot(i); slot != nil && slot.ItemID == itemID && slot.Quality == quality && slot.MaxQuality == maxQuality { slot.Quantity += qty return } -- cgit v1.2.3