Files
bd2/go/internal/server/player/commerce_items.go
T
Flechazo d8771caef2 feat(all): add hunting and events, commerce and rewards, binary calendars, GameData caching and login diagnostics
Implement hunting AP and progress, event tasks, exchanges, games, stories and actions; connect battle and reward handling.

Add CashShop plugin and installation, server purchases and entitlements, recharge rules and plugin version metadata.

Distribute binary calendars independently; cache GameData in memory and fix single-connection query deadlocks.

Improve automatic login and recovery diagnostics; document configuration and release flows.
2026-10-05 11:50:31 +08:00

77 lines
2.0 KiB
Go

package player
import (
"fmt"
"math"
)
// GrantCommerceOnce preserves the exact item expiry supplied by the commerce
// entitlement policy. It shares the existing atomic inventory layout.
func (s *Inventory) GrantCommerceOnce(identity string, rewards []Item) ([]Item, error) {
if identity == "" {
return nil, fmt.Errorf("player: missing commerce reward identity")
}
s.mu.Lock()
defer s.mu.Unlock()
if s.owned.Granted[identity] {
var out []Item
for _, idx := range s.owned.GrantItems[identity] {
for _, item := range s.owned.Items {
if item.InvenIndex == idx {
out = append(out, item)
}
}
}
return out, nil
}
next := cloneOwnedSnapshot(s.owned)
var out []Item
for _, r := range rewards {
if r.ID == 0 || (r.Type != 62 && r.Type != 19) || r.Count == 0 || r.Count > math.MaxInt32 || r.Type == 19 && r.ExpiryTime == 0 || next.NextIndex == math.MaxUint64 {
return nil, fmt.Errorf("player: invalid commerce item")
}
if r.Type == 19 {
found := false
for i, current := range next.Items {
if current.Type == 19 && current.ID == r.ID {
r.InvenIndex = current.InvenIndex
r.Count = 1
next.Items[i] = r
next.GrantItems[identity] = append(next.GrantItems[identity], r.InvenIndex)
out = append(out, r)
found = true
break
}
}
if found {
continue
}
r.Count = 1
}
r.InvenIndex = next.NextIndex
next.NextIndex++
next.Items = append(next.Items, r)
next.GrantItems[identity] = append(next.GrantItems[identity], r.InvenIndex)
out = append(out, r)
}
next.Granted[identity] = true
if err := s.commitOwned(next); err != nil {
return nil, err
}
s.owned = next
return out, nil
}
func (s *Inventory) ContentTicketExpiry(id uint64) uint64 {
s.mu.Lock()
defer s.mu.Unlock()
var expiry uint64
for _, items := range [][]Item{s.starter.Items, s.owned.Items} {
for _, i := range items {
if i.Type == 19 && i.ID == id && i.Count > 0 && i.ExpiryTime > expiry {
expiry = i.ExpiryTime
}
}
}
return expiry
}