670 lines
18 KiB
Go
670 lines
18 KiB
Go
package loot
|
|
|
|
import (
|
|
"database/sql"
|
|
"testing"
|
|
"time"
|
|
|
|
"eq2emu/internal/items"
|
|
|
|
_ "zombiezen.com/go/sqlite"
|
|
)
|
|
|
|
// Test helper functions and mock implementations
|
|
|
|
// MockItemMasterList implements items.MasterItemListService for testing
|
|
type MockItemMasterList struct {
|
|
items map[int32]*items.Item
|
|
}
|
|
|
|
func NewMockItemMasterList() *MockItemMasterList {
|
|
return &MockItemMasterList{
|
|
items: make(map[int32]*items.Item),
|
|
}
|
|
}
|
|
|
|
func (m *MockItemMasterList) GetItem(itemID int32) *items.Item {
|
|
return m.items[itemID]
|
|
}
|
|
|
|
func (m *MockItemMasterList) AddTestItem(itemID int32, name string, tier int8) {
|
|
item := &items.Item{
|
|
Name: name,
|
|
Details: items.ItemDetails{
|
|
ItemID: itemID,
|
|
Tier: tier,
|
|
},
|
|
GenericInfo: items.ItemGenericInfo{
|
|
ItemType: items.ItemTypeNormal,
|
|
},
|
|
}
|
|
item.Details.UniqueID = items.NextUniqueItemID()
|
|
m.items[itemID] = item
|
|
}
|
|
|
|
// MockPlayerService implements PlayerService for testing
|
|
type MockPlayerService struct {
|
|
playerPositions map[uint32][5]float32 // x, y, z, heading, zoneID
|
|
inventorySpace map[uint32]int
|
|
combat map[uint32]bool
|
|
skills map[uint32]map[string]int32
|
|
}
|
|
|
|
func NewMockPlayerService() *MockPlayerService {
|
|
return &MockPlayerService{
|
|
playerPositions: make(map[uint32][5]float32),
|
|
inventorySpace: make(map[uint32]int),
|
|
combat: make(map[uint32]bool),
|
|
skills: make(map[uint32]map[string]int32),
|
|
}
|
|
}
|
|
|
|
func (m *MockPlayerService) GetPlayerPosition(playerID uint32) (x, y, z, heading float32, zoneID int32, err error) {
|
|
pos := m.playerPositions[playerID]
|
|
return pos[0], pos[1], pos[2], pos[3], int32(pos[4]), nil
|
|
}
|
|
|
|
func (m *MockPlayerService) IsPlayerInCombat(playerID uint32) bool {
|
|
return m.combat[playerID]
|
|
}
|
|
|
|
func (m *MockPlayerService) CanPlayerCarryItems(playerID uint32, itemCount int) bool {
|
|
space := m.inventorySpace[playerID]
|
|
return space >= itemCount
|
|
}
|
|
|
|
func (m *MockPlayerService) AddItemsToPlayer(playerID uint32, items []*items.Item) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockPlayerService) AddCoinsToPlayer(playerID uint32, coins int32) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockPlayerService) GetPlayerSkillValue(playerID uint32, skillName string) int32 {
|
|
if skills, exists := m.skills[playerID]; exists {
|
|
return skills[skillName]
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (m *MockPlayerService) AddPlayerExperience(playerID uint32, experience int32, skillName string) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockPlayerService) SendMessageToPlayer(playerID uint32, message string) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockPlayerService) SetPlayerPosition(playerID uint32, x, y, z, heading float32, zoneID int32) {
|
|
m.playerPositions[playerID] = [5]float32{x, y, z, heading, float32(zoneID)}
|
|
}
|
|
|
|
func (m *MockPlayerService) SetInventorySpace(playerID uint32, space int) {
|
|
m.inventorySpace[playerID] = space
|
|
}
|
|
|
|
// MockZoneService implements ZoneService for testing
|
|
type MockZoneService struct {
|
|
rules map[int32]map[string]interface{}
|
|
objects map[int32]map[int32]interface{} // zoneID -> objectID
|
|
}
|
|
|
|
func NewMockZoneService() *MockZoneService {
|
|
return &MockZoneService{
|
|
rules: make(map[int32]map[string]interface{}),
|
|
objects: make(map[int32]map[int32]interface{}),
|
|
}
|
|
}
|
|
|
|
func (m *MockZoneService) GetZoneRule(zoneID int32, ruleName string) (interface{}, error) {
|
|
if rules, exists := m.rules[zoneID]; exists {
|
|
return rules[ruleName], nil
|
|
}
|
|
return true, nil // Default to enabled
|
|
}
|
|
|
|
func (m *MockZoneService) SpawnObjectInZone(zoneID int32, appearanceID int32, x, y, z, heading float32, name string, commands []string) (int32, error) {
|
|
objectID := int32(len(m.objects[zoneID]) + 1)
|
|
if m.objects[zoneID] == nil {
|
|
m.objects[zoneID] = make(map[int32]interface{})
|
|
}
|
|
m.objects[zoneID][objectID] = struct{}{}
|
|
return objectID, nil
|
|
}
|
|
|
|
func (m *MockZoneService) RemoveObjectFromZone(zoneID int32, objectID int32) error {
|
|
if objects, exists := m.objects[zoneID]; exists {
|
|
delete(objects, objectID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *MockZoneService) GetDistanceBetweenPoints(x1, y1, z1, x2, y2, z2 float32) float32 {
|
|
dx := x1 - x2
|
|
dy := y1 - y2
|
|
dz := z1 - z2
|
|
return float32(dx*dx + dy*dy + dz*dz) // Simplified distance calculation
|
|
}
|
|
|
|
// Test database setup
|
|
func setupTestDatabase(t *testing.T) *sql.DB {
|
|
db, err := sql.Open("sqlite", ":memory:")
|
|
if err != nil {
|
|
t.Fatalf("Failed to open test database: %v", err)
|
|
}
|
|
|
|
schema := `
|
|
CREATE TABLE loottable (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT,
|
|
mincoin INTEGER DEFAULT 0,
|
|
maxcoin INTEGER DEFAULT 0,
|
|
maxlootitems INTEGER DEFAULT 6,
|
|
lootdrop_probability REAL DEFAULT 100.0,
|
|
coin_probability REAL DEFAULT 50.0
|
|
);
|
|
|
|
CREATE TABLE lootdrop (
|
|
loot_table_id INTEGER,
|
|
item_id INTEGER,
|
|
item_charges INTEGER DEFAULT 1,
|
|
equip_item INTEGER DEFAULT 0,
|
|
probability REAL DEFAULT 100.0,
|
|
no_drop_quest_completed_id INTEGER DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE spawn_loot (
|
|
spawn_id INTEGER,
|
|
loottable_id INTEGER
|
|
);
|
|
|
|
CREATE TABLE loot_global (
|
|
type TEXT,
|
|
loot_table INTEGER,
|
|
value1 INTEGER,
|
|
value2 INTEGER,
|
|
value3 INTEGER,
|
|
value4 INTEGER
|
|
);
|
|
`
|
|
|
|
if _, err := db.Exec(schema); err != nil {
|
|
t.Fatalf("Failed to create test schema: %v", err)
|
|
}
|
|
|
|
return db
|
|
}
|
|
|
|
// Insert test data
|
|
func insertTestLootData(t *testing.T, db *sql.DB) {
|
|
// Test loot table
|
|
_, err := db.Exec(`
|
|
INSERT INTO loottable (id, name, mincoin, maxcoin, maxlootitems, lootdrop_probability, coin_probability)
|
|
VALUES (1, 'Test Loot Table', 10, 50, 3, 100.0, 75.0)
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test loot table: %v", err)
|
|
}
|
|
|
|
// Test loot drops
|
|
lootDrops := []struct {
|
|
tableID int32
|
|
itemID int32
|
|
charges int16
|
|
probability float32
|
|
}{
|
|
{1, 101, 1, 100.0}, // Always drops
|
|
{1, 102, 5, 50.0}, // 50% chance
|
|
{1, 103, 1, 25.0}, // 25% chance
|
|
}
|
|
|
|
for _, drop := range lootDrops {
|
|
_, err := db.Exec(`
|
|
INSERT INTO lootdrop (loot_table_id, item_id, item_charges, probability)
|
|
VALUES (?, ?, ?, ?)
|
|
`, drop.tableID, drop.itemID, drop.charges, drop.probability)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert loot drop: %v", err)
|
|
}
|
|
}
|
|
|
|
// Test spawn loot assignment
|
|
_, err = db.Exec(`
|
|
INSERT INTO spawn_loot (spawn_id, loottable_id)
|
|
VALUES (1001, 1)
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert spawn loot: %v", err)
|
|
}
|
|
|
|
// Test global loot
|
|
_, err = db.Exec(`
|
|
INSERT INTO loot_global (type, loot_table, value1, value2, value3, value4)
|
|
VALUES ('level', 1, 10, 20, 1, 0)
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert global loot: %v", err)
|
|
}
|
|
}
|
|
|
|
// Test Functions
|
|
|
|
func TestNewLootDatabase(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
if lootDB == nil {
|
|
t.Fatal("Expected non-nil LootDatabase")
|
|
}
|
|
|
|
if lootDB.db != db {
|
|
t.Error("Expected database connection to be set")
|
|
}
|
|
|
|
if len(lootDB.queries) == 0 {
|
|
t.Error("Expected queries to be prepared")
|
|
}
|
|
}
|
|
|
|
func TestLoadLootData(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
insertTestLootData(t, db)
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
err := lootDB.LoadAllLootData()
|
|
if err != nil {
|
|
t.Fatalf("Failed to load loot data: %v", err)
|
|
}
|
|
|
|
// Test loot table loaded
|
|
table := lootDB.GetLootTable(1)
|
|
if table == nil {
|
|
t.Fatal("Expected to find loot table 1")
|
|
}
|
|
|
|
if table.Name != "Test Loot Table" {
|
|
t.Errorf("Expected table name 'Test Loot Table', got '%s'", table.Name)
|
|
}
|
|
|
|
if len(table.Drops) != 3 {
|
|
t.Errorf("Expected 3 loot drops, got %d", len(table.Drops))
|
|
}
|
|
|
|
// Test spawn loot assignment
|
|
tables := lootDB.GetSpawnLootTables(1001)
|
|
if len(tables) != 1 || tables[0] != 1 {
|
|
t.Errorf("Expected spawn 1001 to have loot table 1, got %v", tables)
|
|
}
|
|
|
|
// Test global loot
|
|
globalLoot := lootDB.GetGlobalLootTables(15, 0, 0)
|
|
if len(globalLoot) != 1 {
|
|
t.Errorf("Expected 1 global loot entry for level 15, got %d", len(globalLoot))
|
|
}
|
|
}
|
|
|
|
func TestLootManager(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
insertTestLootData(t, db)
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
err := lootDB.LoadAllLootData()
|
|
if err != nil {
|
|
t.Fatalf("Failed to load loot data: %v", err)
|
|
}
|
|
|
|
// Create mock item master list
|
|
itemList := NewMockItemMasterList()
|
|
itemList.AddTestItem(101, "Test Sword", LootTierCommon)
|
|
itemList.AddTestItem(102, "Test Potion", LootTierCommon)
|
|
itemList.AddTestItem(103, "Test Shield", LootTierTreasured)
|
|
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
|
|
// Test loot generation
|
|
context := &LootContext{
|
|
PlayerLevel: 15,
|
|
PlayerRace: 1,
|
|
ZoneID: 100,
|
|
KillerID: 1,
|
|
GroupMembers: []uint32{1},
|
|
CompletedQuests: make(map[int32]bool),
|
|
LootMethod: GroupLootMethodFreeForAll,
|
|
}
|
|
|
|
result, err := lootManager.GenerateLoot(1001, context)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate loot: %v", err)
|
|
}
|
|
|
|
if result == nil {
|
|
t.Fatal("Expected non-nil loot result")
|
|
}
|
|
|
|
// Should have at least one item (100% drop chance for item 101)
|
|
items := result.GetItems()
|
|
if len(items) == 0 {
|
|
t.Error("Expected at least one item in loot result")
|
|
}
|
|
|
|
// Should have coins (75% probability)
|
|
coins := result.GetCoins()
|
|
t.Logf("Generated %d items and %d coins", len(items), coins)
|
|
}
|
|
|
|
func TestTreasureChestCreation(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
itemList := NewMockItemMasterList()
|
|
itemList.AddTestItem(101, "Test Item", LootTierLegendary) // High tier for ornate chest
|
|
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
|
|
// Create loot result
|
|
item := itemList.GetItem(101)
|
|
lootResult := &LootResult{
|
|
Items: []*items.Item{item},
|
|
Coins: 100,
|
|
}
|
|
|
|
// Create treasure chest
|
|
chest, err := lootManager.CreateTreasureChest(1001, 100, 10.0, 20.0, 30.0, 0.0, lootResult, []uint32{1, 2})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create treasure chest: %v", err)
|
|
}
|
|
|
|
if chest.AppearanceID != ChestAppearanceOrnate {
|
|
t.Errorf("Expected ornate chest appearance %d for legendary item, got %d",
|
|
ChestAppearanceOrnate, chest.AppearanceID)
|
|
}
|
|
|
|
if len(chest.LootRights) != 2 {
|
|
t.Errorf("Expected 2 players with loot rights, got %d", len(chest.LootRights))
|
|
}
|
|
|
|
if !chest.HasLootRights(1) {
|
|
t.Error("Expected player 1 to have loot rights")
|
|
}
|
|
|
|
if chest.HasLootRights(3) {
|
|
t.Error("Expected player 3 to not have loot rights")
|
|
}
|
|
}
|
|
|
|
func TestChestService(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
itemList := NewMockItemMasterList()
|
|
itemList.AddTestItem(101, "Test Item", LootTierCommon)
|
|
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
|
|
// Create mock services
|
|
playerService := NewMockPlayerService()
|
|
zoneService := NewMockZoneService()
|
|
|
|
// Set up player near chest
|
|
playerService.SetPlayerPosition(1, 10.0, 20.0, 30.0, 0.0, 100)
|
|
playerService.SetInventorySpace(1, 10)
|
|
|
|
chestService := NewChestService(lootManager, playerService, zoneService)
|
|
|
|
// Create loot and chest
|
|
item := itemList.GetItem(101)
|
|
lootResult := &LootResult{
|
|
Items: []*items.Item{item},
|
|
Coins: 50,
|
|
}
|
|
|
|
chest, err := chestService.CreateTreasureChestFromLoot(1001, 100, 10.0, 20.0, 30.0, 0.0, lootResult, []uint32{1})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create treasure chest: %v", err)
|
|
}
|
|
|
|
// Test viewing chest
|
|
result := chestService.HandleChestInteraction(chest.ID, 1, ChestInteractionView, 0)
|
|
if !result.Success {
|
|
t.Errorf("Expected successful chest view, got: %s", result.Message)
|
|
}
|
|
|
|
if len(result.Items) != 1 {
|
|
t.Errorf("Expected 1 item in view result, got %d", len(result.Items))
|
|
}
|
|
|
|
// Test looting item
|
|
result = chestService.HandleChestInteraction(chest.ID, 1, ChestInteractionLoot, item.Details.UniqueID)
|
|
if !result.Success {
|
|
t.Errorf("Expected successful item loot, got: %s", result.Message)
|
|
}
|
|
|
|
if len(result.Items) != 1 {
|
|
t.Errorf("Expected 1 looted item, got %d", len(result.Items))
|
|
}
|
|
|
|
// Chest should now be empty of items but still have coins
|
|
if lootManager.IsChestEmpty(chest.ID) {
|
|
t.Error("Expected chest to still have coins")
|
|
}
|
|
|
|
// Test looting all remaining (coins)
|
|
result = chestService.HandleChestInteraction(chest.ID, 1, ChestInteractionLootAll, 0)
|
|
if !result.Success {
|
|
t.Errorf("Expected successful loot all, got: %s", result.Message)
|
|
}
|
|
|
|
if result.Coins != 50 {
|
|
t.Errorf("Expected 50 coins looted, got %d", result.Coins)
|
|
}
|
|
|
|
// Chest should now be empty
|
|
if !lootManager.IsChestEmpty(chest.ID) {
|
|
t.Error("Expected chest to be empty after looting all")
|
|
}
|
|
}
|
|
|
|
func TestLootStatistics(t *testing.T) {
|
|
stats := NewLootStatistics()
|
|
|
|
// Create test loot result
|
|
item := &items.Item{
|
|
Details: items.ItemDetails{
|
|
ItemID: 101,
|
|
Tier: LootTierRare,
|
|
},
|
|
}
|
|
|
|
lootResult := &LootResult{
|
|
Items: []*items.Item{item},
|
|
Coins: 100,
|
|
}
|
|
|
|
// Record loot
|
|
stats.RecordLoot(1, lootResult)
|
|
stats.RecordChest()
|
|
|
|
current := stats.GetStatistics()
|
|
|
|
if current.TotalLoots != 1 {
|
|
t.Errorf("Expected 1 total loot, got %d", current.TotalLoots)
|
|
}
|
|
|
|
if current.TotalItems != 1 {
|
|
t.Errorf("Expected 1 total item, got %d", current.TotalItems)
|
|
}
|
|
|
|
if current.TotalCoins != 100 {
|
|
t.Errorf("Expected 100 total coins, got %d", current.TotalCoins)
|
|
}
|
|
|
|
if current.TreasureChests != 1 {
|
|
t.Errorf("Expected 1 treasure chest, got %d", current.TreasureChests)
|
|
}
|
|
|
|
if current.ItemsByTier[LootTierRare] != 1 {
|
|
t.Errorf("Expected 1 rare item, got %d", current.ItemsByTier[LootTierRare])
|
|
}
|
|
}
|
|
|
|
func TestChestAppearanceSelection(t *testing.T) {
|
|
testCases := []struct {
|
|
tier int8
|
|
expected int32
|
|
}{
|
|
{LootTierCommon, ChestAppearanceSmall},
|
|
{LootTierTreasured, ChestAppearanceTreasure},
|
|
{LootTierLegendary, ChestAppearanceOrnate},
|
|
{LootTierFabled, ChestAppearanceExquisite},
|
|
{LootTierMythical, ChestAppearanceExquisite},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
appearance := GetChestAppearance(tc.tier)
|
|
if appearance.AppearanceID != tc.expected {
|
|
t.Errorf("For tier %d, expected appearance %d, got %d",
|
|
tc.tier, tc.expected, appearance.AppearanceID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLootValidation(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
itemList := NewMockItemMasterList()
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
|
|
playerService := NewMockPlayerService()
|
|
zoneService := NewMockZoneService()
|
|
chestService := NewChestService(lootManager, playerService, zoneService)
|
|
|
|
// Create a chest with loot rights for player 1
|
|
lootResult := &LootResult{Items: []*items.Item{}, Coins: 100}
|
|
chest, _ := lootManager.CreateTreasureChest(1001, 100, 10.0, 20.0, 30.0, 0.0, lootResult, []uint32{1})
|
|
|
|
// Test player without loot rights
|
|
result := chestService.HandleChestInteraction(chest.ID, 2, ChestInteractionView, 0)
|
|
if result.Success {
|
|
t.Error("Expected failure for player without loot rights")
|
|
}
|
|
if result.Result != ChestResultNoRights {
|
|
t.Errorf("Expected no rights result, got %d", result.Result)
|
|
}
|
|
|
|
// Test player in combat
|
|
playerService.SetPlayerPosition(1, 10.0, 20.0, 30.0, 0.0, 100)
|
|
playerService.combat[1] = true
|
|
result = chestService.HandleChestInteraction(chest.ID, 1, ChestInteractionView, 0)
|
|
if result.Success {
|
|
t.Error("Expected failure for player in combat")
|
|
}
|
|
if result.Result != ChestResultInCombat {
|
|
t.Errorf("Expected in combat result, got %d", result.Result)
|
|
}
|
|
|
|
// Test player too far away
|
|
playerService.combat[1] = false
|
|
playerService.SetPlayerPosition(1, 100.0, 100.0, 100.0, 0.0, 100)
|
|
result = chestService.HandleChestInteraction(chest.ID, 1, ChestInteractionView, 0)
|
|
if result.Success {
|
|
t.Error("Expected failure for player too far away")
|
|
}
|
|
if result.Result != ChestResultTooFar {
|
|
t.Errorf("Expected too far result, got %d", result.Result)
|
|
}
|
|
}
|
|
|
|
func TestCleanupExpiredChests(t *testing.T) {
|
|
db := setupTestDatabase(t)
|
|
defer db.Close()
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
itemList := NewMockItemMasterList()
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
|
|
// Create an empty chest (should be cleaned up quickly)
|
|
emptyResult := &LootResult{Items: []*items.Item{}, Coins: 0}
|
|
emptyChest, _ := lootManager.CreateTreasureChest(1001, 100, 10.0, 20.0, 30.0, 0.0, emptyResult, []uint32{1})
|
|
|
|
// Modify the created time to make it expired
|
|
emptyChest.Created = time.Now().Add(-time.Duration(ChestDespawnTime+1) * time.Second)
|
|
|
|
// Run cleanup
|
|
lootManager.CleanupExpiredChests()
|
|
|
|
// Check that empty chest was removed
|
|
if lootManager.GetTreasureChest(emptyChest.ID) != nil {
|
|
t.Error("Expected expired empty chest to be cleaned up")
|
|
}
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkLootGeneration(b *testing.B) {
|
|
db := setupTestDatabase(b)
|
|
defer db.Close()
|
|
|
|
insertTestLootData(b, db)
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
lootDB.LoadAllLootData()
|
|
|
|
itemList := NewMockItemMasterList()
|
|
itemList.AddTestItem(101, "Test Item", LootTierCommon)
|
|
itemList.AddTestItem(102, "Test Item 2", LootTierCommon)
|
|
itemList.AddTestItem(103, "Test Item 3", LootTierCommon)
|
|
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
|
|
context := &LootContext{
|
|
PlayerLevel: 15,
|
|
CompletedQuests: make(map[int32]bool),
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
_, err := lootManager.GenerateLoot(1001, context)
|
|
if err != nil {
|
|
b.Fatalf("Failed to generate loot: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkChestInteraction(b *testing.B) {
|
|
db := setupTestDatabase(b)
|
|
defer db.Close()
|
|
|
|
lootDB := NewLootDatabase(db)
|
|
itemList := NewMockItemMasterList()
|
|
itemList.AddTestItem(101, "Test Item", LootTierCommon)
|
|
|
|
lootManager := NewLootManager(lootDB, itemList)
|
|
playerService := NewMockPlayerService()
|
|
zoneService := NewMockZoneService()
|
|
chestService := NewChestService(lootManager, playerService, zoneService)
|
|
|
|
// Set up player
|
|
playerService.SetPlayerPosition(1, 10.0, 20.0, 30.0, 0.0, 100)
|
|
playerService.SetInventorySpace(1, 100)
|
|
|
|
// Create chest with loot
|
|
item := itemList.GetItem(101)
|
|
lootResult := &LootResult{Items: []*items.Item{item}, Coins: 100}
|
|
chest, _ := chestService.CreateTreasureChestFromLoot(1001, 100, 10.0, 20.0, 30.0, 0.0, lootResult, []uint32{1})
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
chestService.HandleChestInteraction(chest.ID, 1, ChestInteractionView, 0)
|
|
}
|
|
} |