130 lines
4.2 KiB
Go
130 lines
4.2 KiB
Go
package eventtasks
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
"bd2server/internal/server/events"
|
|
"bd2server/internal/server/gamedata"
|
|
"bd2server/internal/server/player"
|
|
"bd2server/internal/server/stateio"
|
|
"bd2server/internal/server/wire"
|
|
)
|
|
|
|
type passRewardDesign struct{}
|
|
|
|
func (passRewardDesign) Character(uint64) (gamedata.CharacterDesign, bool) {
|
|
return gamedata.CharacterDesign{}, false
|
|
}
|
|
func (passRewardDesign) RollOptions(uint64) ([]gamedata.EquipmentOptionChoice, []gamedata.EquipmentOptionChoice, *gamedata.EquipmentOptionChoice, error) {
|
|
return nil, nil, nil, nil
|
|
}
|
|
func (passRewardDesign) Resolve(r []gamedata.BattleReward) ([]gamedata.BattleReward, error) {
|
|
return r, nil
|
|
}
|
|
|
|
func realPassEconomy(t *testing.T, store stateio.Store) (*events.Economy, *player.Inventory, *player.Wallet) {
|
|
t.Helper()
|
|
items, err := player.OpenInventory(store, &player.Starter{Version: "2.35.10"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wallet, err := player.OpenWallet(store, player.Currency{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
collection, err := player.OpenCollectionStore(store, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
equipment, err := player.OpenEquipmentInventory(store)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, persist := range []func() error{items.EnsurePersisted, wallet.EnsurePersisted, collection.EnsurePersisted, equipment.EnsurePersisted} {
|
|
if err := persist(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
design := passRewardDesign{}
|
|
economy, err := events.NewEconomy(store, items, wallet, collection, equipment, design, design, design, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return economy, items, wallet
|
|
}
|
|
|
|
// A spy alone cannot detect a claim recorded without a durable inventory grant.
|
|
// Exercise the native BASIC -> PREMIUM one-click flow through the real economy.
|
|
func TestPassRewardAllPersistsEveryCurrencyAndItemAcrossRestart(t *testing.T) {
|
|
s, _, store := setup(t)
|
|
economy, items, wallet := realPassEconomy(t, store)
|
|
s.economy = economy
|
|
s.design.PassLevels[8] = []gamedata.EventPassLevel{
|
|
{ID: 1, NeedExp: 20, Basic: gamedata.Reward{Type: 3, Count: 5}, Premium: gamedata.Reward{Type: 8, ID: 1000, Count: 2}},
|
|
{ID: 2, NeedExp: 30, Basic: gamedata.Reward{Type: 3, Count: 7}, Premium: gamedata.Reward{Type: 8, ID: 1000, Count: 3}},
|
|
{ID: 3, NeedExp: 40, Basic: gamedata.Reward{Type: 8, ID: 1000, Count: 11}, Premium: gamedata.Reward{Type: 4, Count: 100}},
|
|
{ID: 4, Basic: gamedata.Reward{Type: 3, Count: 999}, Premium: gamedata.Reward{Type: 4, Count: 999}},
|
|
}
|
|
p := s.pass(s.registry.List()[2])
|
|
p.Exp = 50
|
|
p.Premium = true
|
|
basic := passClaimRequest(1, 0, true, 0)
|
|
premium := passClaimRequest(2, 1, true, 0)
|
|
basicReply := claimPass(t, s, basic)
|
|
premiumReply := claimPass(t, s, premium)
|
|
assertBalances := func(items *player.Inventory, wallet *player.Wallet) {
|
|
t.Helper()
|
|
c := wallet.Snapshot()
|
|
if c.FreeJewelry != 12 || c.Gold != 100 {
|
|
t.Fatalf("durable currencies: %+v", c)
|
|
}
|
|
var total uint64
|
|
for _, item := range items.All() {
|
|
if item.Type == 8 && item.ID == 1000 {
|
|
total += item.Count
|
|
}
|
|
}
|
|
if total != 16 {
|
|
t.Fatalf("durable ticket quantity=%d want=16", total)
|
|
}
|
|
}
|
|
assertBalances(items, wallet)
|
|
for _, response := range [][]byte{basicReply, premiumReply} {
|
|
bundle, _, err := wire.Bytes(response, 1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
count := 0
|
|
if err := wire.Walk(bundle, func(f wire.Field) error {
|
|
if f.Number == 1 {
|
|
count++
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if count != 3 {
|
|
t.Fatalf("bundle omitted rewards: entries=%d want=3", count)
|
|
}
|
|
}
|
|
economy, items, wallet = realPassEconomy(t, store)
|
|
reopened, err := Open(store, s.design, s.registry, economy)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
reopened.now = s.now
|
|
reopened.SetSession("test")
|
|
if !bytes.Equal(claimPass(t, reopened, basic), basicReply) || !bytes.Equal(claimPass(t, reopened, premium), premiumReply) {
|
|
t.Fatal("replay response changed")
|
|
}
|
|
assertBalances(items, wallet)
|
|
for typ := uint64(0); typ <= 1; typ++ {
|
|
claimPass(t, reopened, passClaimRequest(3+typ, typ, true, 0))
|
|
}
|
|
assertBalances(items, wallet)
|
|
if reopened.pass(reopened.registry.List()[2]).Claimed[key(4, 0)] || reopened.pass(reopened.registry.List()[2]).Claimed[key(4, 1)] {
|
|
t.Fatal("locked level was claimed")
|
|
}
|
|
}
|