Files
bd2/go/internal/server/player/inventory_slots_test.go
T

131 lines
4.9 KiB
Go

package player
import (
"os"
"path/filepath"
"testing"
"bd2server/internal/server/gamedata"
"bd2server/internal/server/stateio"
"bd2server/internal/server/wire"
)
func inventorySlotTestDesign() *gamedata.InventorySlotDesign {
return &gamedata.InventorySlotDesign{
Items: gamedata.InventorySlotRule{Default: 100, Maximum: 500, PriceType: 4, BasePrice: 300, MaxPrice: 10000},
Storage: gamedata.InventorySlotRule{Default: 100, Maximum: 400, PriceType: 4, BasePrice: 300, MaxPrice: 10000},
Equipment: gamedata.InventorySlotRule{Default: 500, Maximum: 2000, PriceType: 4, BasePrice: 300, MaxPrice: 10000},
EquipmentStorage: gamedata.InventorySlotRule{Default: 100, Maximum: 400, PriceType: 4, BasePrice: 300, MaxPrice: 10000},
}
}
func inventorySlotTestCounts() InventorySlotCounts {
return InventorySlotCounts{Items: 100, Storage: 100, Equipment: 500, EquipmentStorage: 100}
}
func TestInventorySlotExpansionChargesPersistsAndReplays(t *testing.T) {
store := stateio.NewMemory()
wallet, err := OpenWallet(store, Currency{Gold: 100000})
if err != nil {
t.Fatal(err)
}
slots, err := OpenInventorySlots(store, inventorySlotTestDesign(), inventorySlotTestCounts(), wallet)
if err != nil {
t.Fatal(err)
}
slots.BeginSession("test")
request := wire.AppendVarint(wire.AppendVarint(nil, 1, 7), 2, 2)
code, response, ok, err := slots.Handle("/InvenAddSlot", request)
if err != nil || !ok || code != 24 || len(response) != 0 {
t.Fatalf("code=%d response=%x ok=%t err=%v", code, response, ok, err)
}
if wallet.Snapshot().Gold != 99100 { // first two slots cost 400 + 500
t.Fatalf("gold=%d", wallet.Snapshot().Gold)
}
if _, _, _, err := slots.Handle("/InvenAddSlot", request); err != nil {
t.Fatal(err)
}
if wallet.Snapshot().Gold != 99100 {
t.Fatalf("replay charged twice: %d", wallet.Snapshot().Gold)
}
reopened, err := OpenInventorySlots(store, inventorySlotTestDesign(), inventorySlotTestCounts(), wallet)
if err != nil {
t.Fatal(err)
}
counts, err := reopened.InventorySlotCounts()
if err != nil || counts.Items != 102 {
t.Fatalf("counts=%+v err=%v", counts, err)
}
}
func TestInventorySlotEndpointsUseTheirProtocolCodes(t *testing.T) {
for path, code := range map[string]int{
"/InvenAddSlot": 24, "/StorageAddSlot": 25, "/EquipAddSlot": 39, "/EquipStorageAddSlot": 82,
} {
t.Run(path, func(t *testing.T) {
store := stateio.NewMemory()
wallet, _ := OpenWallet(store, Currency{Gold: 1000})
slots, _ := OpenInventorySlots(store, inventorySlotTestDesign(), inventorySlotTestCounts(), wallet)
slots.BeginSession("test")
request := wire.AppendVarint(wire.AppendVarint(nil, 1, 1), 2, 1)
got, body, ok, err := slots.Handle(path, request)
if err != nil || !ok || got != code || len(body) != 0 || wallet.Snapshot().Gold != 600 {
t.Fatalf("code=%d body=%x ok=%t gold=%d err=%v", got, body, ok, wallet.Snapshot().Gold, err)
}
})
}
}
func TestUnlimitedInventoryUsesGameDataMaximumAtLoginOnly(t *testing.T) {
store := stateio.NewMemory()
wallet, _ := OpenWallet(store, Currency{})
slots, _ := OpenInventorySlots(store, inventorySlotTestDesign(), inventorySlotTestCounts(), wallet)
path := filepath.Join(t.TempDir(), "dev-tools.json")
slots.AttachDevelopmentSettings(path)
if err := os.WriteFile(path, []byte(`{"version":1,"inventory":{"unlimited":true}}`), 0o600); err != nil {
t.Fatal(err)
}
counts, err := slots.InventorySlotCounts()
if err != nil {
t.Fatal(err)
}
if counts.Items != 500 || counts.Equipment != 2000 || counts.Storage != 100 || counts.EquipmentStorage != 100 {
t.Fatalf("counts=%+v", counts)
}
if err := os.WriteFile(path, []byte(`{"version":1,"inventory":{"unlimited":false}}`), 0o600); err != nil {
t.Fatal(err)
}
counts, err = slots.InventorySlotCounts()
if err != nil || counts != inventorySlotTestCounts() {
t.Fatalf("restored counts=%+v err=%v", counts, err)
}
}
func TestUnlimitedInventoryRejectsMalformedDevelopmentSettings(t *testing.T) {
store := stateio.NewMemory()
wallet, _ := OpenWallet(store, Currency{})
slots, _ := OpenInventorySlots(store, inventorySlotTestDesign(), inventorySlotTestCounts(), wallet)
path := filepath.Join(t.TempDir(), "dev-tools.json")
slots.AttachDevelopmentSettings(path)
if err := os.WriteFile(path, []byte(`{"version":1,"inventory":{"unlimited":true},"extra":1}`), 0o600); err != nil {
t.Fatal(err)
}
if _, err := slots.InventorySlotCounts(); err == nil {
t.Fatal("malformed settings accepted")
}
if err := os.WriteFile(path, []byte(`{"version":1}`), 0o600); err != nil {
t.Fatal(err)
}
if _, err := slots.InventorySlotCounts(); err == nil {
t.Fatal("settings without inventory accepted")
}
}
func TestInventorySlotPriceCapsEachAddedSlot(t *testing.T) {
rule := gamedata.InventorySlotRule{Default: 100, Maximum: 500, PriceType: 4, BasePrice: 300, MaxPrice: 10000}
price, err := inventorySlotPrice(rule, 196, 2)
if err != nil || price != 20000 {
t.Fatalf("price=%d err=%v", price, err)
}
}