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 }