Files
bd2/go/internal/server/world/pack_jam.go
T
Flechazo 5b5a219dc2 feat(server): add special loot and data-driven gameplay rules
Generate equipment loot atomically, grant random boxes and prevent repeat claims.
Read gacha pools, pity, products, tickets, missions, presets, chapter rewards
and inventory costs from GameData; extend both collaboration UR ticket pools.
Sync owned recipes, configure startup state and calendars in versioned seeds,
and validate unlock tickets and revival talents.
2026-10-04 19:15:59 +08:00

54 lines
1.8 KiB
Go

package world
import (
"fmt"
"bd2server/internal/server/gamedata"
"bd2server/internal/server/wire"
)
func packJamIdentity(packID int) string { return fmt.Sprintf("pack-jam:%d", packID) }
func (s *Service) handlePackDocking(path string, request []byte) (int, []byte, bool, error) {
packID, err := requestPack(request)
if err != nil {
return 0, nil, true, err
}
if _, known := s.questsFor(packID); !known || !s.packUnlocked(packID) {
return 0, nil, true, fmt.Errorf("%w: unavailable docking pack %d", ErrInvalidRequest, packID)
}
if s.wallet == nil || s.packJamDesign == nil {
return 0, nil, true, fmt.Errorf("world: pack jam design or wallet unavailable")
}
identity := packJamIdentity(packID)
if path == "/PackPreviewInfo" {
var response []byte
if active := s.firstUnclearedQuestFor(packID); active != 0 {
quest := wire.AppendVarint(nil, 1, uint64(active))
quest = wire.AppendVarint(quest, 6, uint64(packID))
response = wire.AppendBytes(response, 1, quest)
}
if s.wallet.WasGranted(identity) {
response = wire.AppendVarint(response, 3, 1)
}
return 104, response, true, nil
}
// Serialize the claim check and grant so concurrent domain callers cannot
// return the animation reward twice. The wallet commits balance and ledger together.
s.packJamMu.Lock()
defer s.packJamMu.Unlock()
if s.wallet.WasGranted(identity) {
return 72, nil, true, nil
}
reward := s.packJamDesign.Reward
if s.packJamDesign.ValidateReward() != nil {
return 0, nil, true, fmt.Errorf("world: unsupported pack jam reward")
}
if _, err := s.wallet.GrantQuestOnce(identity, []gamedata.Reward{reward}); err != nil {
return 0, nil, true, fmt.Errorf("world: grant pack jam reward: %w", err)
}
item := wire.AppendVarint(nil, 3, reward.Type)
item = wire.AppendVarint(item, 4, reward.Count)
return 72, wire.AppendBytes(nil, 1, item), true, nil
}