250 lines
6.3 KiB
Go

package ground_spawn
import (
"fmt"
"eq2emu/internal/database"
)
// DatabaseAdapter implements the Database interface using the internal database wrapper
type DatabaseAdapter struct {
db *database.DB
}
// NewDatabaseAdapter creates a new database adapter using the database wrapper
func NewDatabaseAdapter(db *database.DB) *DatabaseAdapter {
return &DatabaseAdapter{
db: db,
}
}
// LoadGroundSpawnEntries loads harvest entries for a ground spawn
func (da *DatabaseAdapter) LoadGroundSpawnEntries(groundspawnID int32) ([]*GroundSpawnEntry, error) {
query := `
SELECT min_skill_level, min_adventure_level, bonus_table, harvest_1, harvest_3,
harvest_5, harvest_imbue, harvest_rare, harvest_10, harvest_coin
FROM groundspawn_entries
WHERE groundspawn_id = ?
ORDER BY min_skill_level ASC
`
var entries []*GroundSpawnEntry
err := da.db.Query(query, func(row *database.Row) error {
entry := &GroundSpawnEntry{}
var bonusTable int32
entry.MinSkillLevel = int16(row.Int(0))
entry.MinAdventureLevel = int16(row.Int(1))
bonusTable = int32(row.Int(2))
entry.Harvest1 = float32(row.Float(3))
entry.Harvest3 = float32(row.Float(4))
entry.Harvest5 = float32(row.Float(5))
entry.HarvestImbue = float32(row.Float(6))
entry.HarvestRare = float32(row.Float(7))
entry.Harvest10 = float32(row.Float(8))
entry.HarvestCoin = float32(row.Float(9))
entry.BonusTable = bonusTable == 1
entries = append(entries, entry)
return nil
}, groundspawnID)
if err != nil {
return nil, fmt.Errorf("failed to query groundspawn entries: %w", err)
}
return entries, nil
}
// LoadGroundSpawnItems loads harvest items for a ground spawn
func (da *DatabaseAdapter) LoadGroundSpawnItems(groundspawnID int32) ([]*GroundSpawnEntryItem, error) {
query := `
SELECT item_id, is_rare, grid_id, quantity
FROM groundspawn_items
WHERE groundspawn_id = ?
ORDER BY item_id ASC
`
var items []*GroundSpawnEntryItem
err := da.db.Query(query, func(row *database.Row) error {
item := &GroundSpawnEntryItem{}
item.ItemID = int32(row.Int(0))
item.IsRare = int8(row.Int(1))
item.GridID = int32(row.Int(2))
item.Quantity = int16(row.Int(3))
items = append(items, item)
return nil
}, groundspawnID)
if err != nil {
return nil, fmt.Errorf("failed to query groundspawn items: %w", err)
}
return items, nil
}
// SaveGroundSpawn saves a ground spawn to the database
func (da *DatabaseAdapter) SaveGroundSpawn(gs *GroundSpawn) error {
if gs == nil {
return fmt.Errorf("ground spawn cannot be nil")
}
query := `
INSERT OR REPLACE INTO groundspawns (
id, name, x, y, z, heading, respawn_timer, collection_skill,
number_harvests, attempts_per_harvest, groundspawn_entry_id,
randomize_heading, zone_id, created_at, updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
`
randomizeHeading := 0
if gs.GetRandomizeHeading() {
randomizeHeading = 1
}
// TODO: Get actual zone ID from spawn
zoneID := int32(1)
err := da.db.Exec(query,
gs.GetID(),
gs.GetName(),
gs.GetX(),
gs.GetY(),
gs.GetZ(),
int16(gs.GetHeading()),
300, // Default 5 minutes respawn timer
gs.GetCollectionSkill(),
gs.GetNumberHarvests(),
gs.GetAttemptsPerHarvest(),
gs.GetGroundSpawnEntryID(),
randomizeHeading,
zoneID,
)
if err != nil {
return fmt.Errorf("failed to save ground spawn %d: %w", gs.GetID(), err)
}
return nil
}
// LoadAllGroundSpawns loads all ground spawns from the database
func (da *DatabaseAdapter) LoadAllGroundSpawns() ([]*GroundSpawn, error) {
query := `
SELECT id, name, x, y, z, heading, collection_skill, number_harvests,
attempts_per_harvest, groundspawn_entry_id, randomize_heading
FROM groundspawns
WHERE zone_id = ?
ORDER BY id ASC
`
// TODO: Support multiple zones
zoneID := int32(1)
var groundSpawns []*GroundSpawn
err := da.db.Query(query, func(row *database.Row) error {
id := int32(row.Int(0))
name := row.Text(1)
x := float32(row.Float(2))
y := float32(row.Float(3))
z := float32(row.Float(4))
heading := float32(row.Float(5))
collectionSkill := row.Text(6)
numberHarvests := int8(row.Int(7))
attemptsPerHarvest := int8(row.Int(8))
groundspawnEntryID := int32(row.Int(9))
randomizeHeading := int32(row.Int(10))
config := GroundSpawnConfig{
GroundSpawnID: groundspawnEntryID,
CollectionSkill: collectionSkill,
NumberHarvests: numberHarvests,
AttemptsPerHarvest: attemptsPerHarvest,
RandomizeHeading: randomizeHeading == 1,
Location: SpawnLocation{
X: x,
Y: y,
Z: z,
Heading: heading,
GridID: 1, // TODO: Load from database
},
Name: name,
Description: fmt.Sprintf("A %s node", collectionSkill),
}
gs := NewGroundSpawn(config)
gs.SetID(id)
groundSpawns = append(groundSpawns, gs)
return nil
}, zoneID)
if err != nil {
return nil, fmt.Errorf("failed to query groundspawns: %w", err)
}
return groundSpawns, nil
}
// DeleteGroundSpawn deletes a ground spawn from the database
func (da *DatabaseAdapter) DeleteGroundSpawn(id int32) error {
query := `DELETE FROM groundspawns WHERE id = ?`
err := da.db.Exec(query, id)
if err != nil {
return fmt.Errorf("failed to delete ground spawn %d: %w", id, err)
}
return nil
}
// LoadPlayerHarvestStatistics loads harvest statistics for a player
func (da *DatabaseAdapter) LoadPlayerHarvestStatistics(playerID int32) (map[string]int64, error) {
query := `
SELECT skill_name, harvest_count
FROM player_harvest_stats
WHERE player_id = ?
`
stats := make(map[string]int64)
err := da.db.Query(query, func(row *database.Row) error {
skillName := row.Text(0)
harvestCount := row.Int64(1)
stats[skillName] = harvestCount
return nil
}, playerID)
if err != nil {
return nil, fmt.Errorf("failed to query player harvest stats: %w", err)
}
return stats, nil
}
// SavePlayerHarvestStatistic saves a player's harvest statistic
func (da *DatabaseAdapter) SavePlayerHarvestStatistic(playerID int32, skillName string, count int64) error {
query := `
INSERT OR REPLACE INTO player_harvest_stats (player_id, skill_name, harvest_count, updated_at)
VALUES (?, ?, ?, datetime('now'))
`
err := da.db.Exec(query, playerID, skillName, count)
if err != nil {
return fmt.Errorf("failed to save player harvest stat: %w", err)
}
return nil
}