fix ground_spawn database file
This commit is contained in:
parent
1c26bb600d
commit
aa362bde07
@ -1,25 +1,34 @@
|
||||
package ground_spawn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"eq2emu/internal/database"
|
||||
"zombiezen.com/go/sqlite"
|
||||
"zombiezen.com/go/sqlite/sqlitex"
|
||||
)
|
||||
|
||||
// DatabaseAdapter implements the Database interface using the internal database wrapper
|
||||
// DatabaseAdapter implements the Database interface using zombiezen.com/go/sqlite
|
||||
type DatabaseAdapter struct {
|
||||
db *database.DB
|
||||
pool *sqlitex.Pool
|
||||
}
|
||||
|
||||
// NewDatabaseAdapter creates a new database adapter using the database wrapper
|
||||
func NewDatabaseAdapter(db *database.DB) *DatabaseAdapter {
|
||||
// NewDatabaseAdapter creates a new database adapter using the sqlite pool
|
||||
func NewDatabaseAdapter(pool *sqlitex.Pool) *DatabaseAdapter {
|
||||
return &DatabaseAdapter{
|
||||
db: db,
|
||||
pool: pool,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadGroundSpawnEntries loads harvest entries for a ground spawn
|
||||
func (da *DatabaseAdapter) LoadGroundSpawnEntries(groundspawnID int32) ([]*GroundSpawnEntry, error) {
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
query := `
|
||||
SELECT min_skill_level, min_adventure_level, bonus_table, harvest_1, harvest_3,
|
||||
harvest_5, harvest_imbue, harvest_rare, harvest_10, harvest_coin
|
||||
@ -29,27 +38,25 @@ func (da *DatabaseAdapter) LoadGroundSpawnEntries(groundspawnID int32) ([]*Groun
|
||||
`
|
||||
|
||||
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
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{groundspawnID},
|
||||
ResultFunc: func(stmt *sqlite.Stmt) error {
|
||||
entry := &GroundSpawnEntry{
|
||||
MinSkillLevel: int16(stmt.ColumnInt64(0)),
|
||||
MinAdventureLevel: int16(stmt.ColumnInt64(1)),
|
||||
BonusTable: stmt.ColumnInt64(2) == 1,
|
||||
Harvest1: float32(stmt.ColumnFloat(3)),
|
||||
Harvest3: float32(stmt.ColumnFloat(4)),
|
||||
Harvest5: float32(stmt.ColumnFloat(5)),
|
||||
HarvestImbue: float32(stmt.ColumnFloat(6)),
|
||||
HarvestRare: float32(stmt.ColumnFloat(7)),
|
||||
Harvest10: float32(stmt.ColumnFloat(8)),
|
||||
HarvestCoin: float32(stmt.ColumnFloat(9)),
|
||||
}
|
||||
entries = append(entries, entry)
|
||||
|
||||
return nil
|
||||
}, groundspawnID)
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query groundspawn entries: %w", err)
|
||||
@ -60,6 +67,13 @@ func (da *DatabaseAdapter) LoadGroundSpawnEntries(groundspawnID int32) ([]*Groun
|
||||
|
||||
// LoadGroundSpawnItems loads harvest items for a ground spawn
|
||||
func (da *DatabaseAdapter) LoadGroundSpawnItems(groundspawnID int32) ([]*GroundSpawnEntryItem, error) {
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
query := `
|
||||
SELECT item_id, is_rare, grid_id, quantity
|
||||
FROM groundspawn_items
|
||||
@ -68,19 +82,19 @@ func (da *DatabaseAdapter) LoadGroundSpawnItems(groundspawnID int32) ([]*GroundS
|
||||
`
|
||||
|
||||
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))
|
||||
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{groundspawnID},
|
||||
ResultFunc: func(stmt *sqlite.Stmt) error {
|
||||
item := &GroundSpawnEntryItem{
|
||||
ItemID: int32(stmt.ColumnInt64(0)),
|
||||
IsRare: int8(stmt.ColumnInt64(1)),
|
||||
GridID: int32(stmt.ColumnInt64(2)),
|
||||
Quantity: int16(stmt.ColumnInt64(3)),
|
||||
}
|
||||
items = append(items, item)
|
||||
|
||||
return nil
|
||||
}, groundspawnID)
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query groundspawn items: %w", err)
|
||||
@ -95,6 +109,13 @@ func (da *DatabaseAdapter) SaveGroundSpawn(gs *GroundSpawn) error {
|
||||
return fmt.Errorf("ground spawn cannot be nil")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
query := `
|
||||
INSERT OR REPLACE INTO groundspawns (
|
||||
id, name, x, y, z, heading, respawn_timer, collection_skill,
|
||||
@ -112,7 +133,8 @@ func (da *DatabaseAdapter) SaveGroundSpawn(gs *GroundSpawn) error {
|
||||
// TODO: Get actual zone ID from spawn
|
||||
zoneID := int32(1)
|
||||
|
||||
err := da.db.Exec(query,
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{
|
||||
gs.GetID(),
|
||||
gs.GetName(),
|
||||
gs.GetX(),
|
||||
@ -126,7 +148,8 @@ func (da *DatabaseAdapter) SaveGroundSpawn(gs *GroundSpawn) error {
|
||||
gs.GetGroundSpawnEntryID(),
|
||||
randomizeHeading,
|
||||
zoneID,
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save ground spawn %d: %w", gs.GetID(), err)
|
||||
@ -137,6 +160,13 @@ func (da *DatabaseAdapter) SaveGroundSpawn(gs *GroundSpawn) error {
|
||||
|
||||
// LoadAllGroundSpawns loads all ground spawns from the database
|
||||
func (da *DatabaseAdapter) LoadAllGroundSpawns() ([]*GroundSpawn, error) {
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
query := `
|
||||
SELECT id, name, x, y, z, heading, collection_skill, number_harvests,
|
||||
attempts_per_harvest, groundspawn_entry_id, randomize_heading
|
||||
@ -149,26 +179,27 @@ func (da *DatabaseAdapter) LoadAllGroundSpawns() ([]*GroundSpawn, error) {
|
||||
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))
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{zoneID},
|
||||
ResultFunc: func(stmt *sqlite.Stmt) error {
|
||||
id := int32(stmt.ColumnInt64(0))
|
||||
name := stmt.ColumnText(1)
|
||||
x := float32(stmt.ColumnFloat(2))
|
||||
y := float32(stmt.ColumnFloat(3))
|
||||
z := float32(stmt.ColumnFloat(4))
|
||||
heading := float32(stmt.ColumnFloat(5))
|
||||
collectionSkill := stmt.ColumnText(6)
|
||||
numberHarvests := int8(stmt.ColumnInt64(7))
|
||||
attemptsPerHarvest := int8(stmt.ColumnInt64(8))
|
||||
groundspawnEntryID := int32(stmt.ColumnInt64(9))
|
||||
randomizeHeading := stmt.ColumnInt64(10) == 1
|
||||
|
||||
config := GroundSpawnConfig{
|
||||
GroundSpawnID: groundspawnEntryID,
|
||||
CollectionSkill: collectionSkill,
|
||||
NumberHarvests: numberHarvests,
|
||||
AttemptsPerHarvest: attemptsPerHarvest,
|
||||
RandomizeHeading: randomizeHeading == 1,
|
||||
RandomizeHeading: randomizeHeading,
|
||||
Location: SpawnLocation{
|
||||
X: x,
|
||||
Y: y,
|
||||
@ -184,9 +215,9 @@ func (da *DatabaseAdapter) LoadAllGroundSpawns() ([]*GroundSpawn, error) {
|
||||
gs.SetID(id)
|
||||
|
||||
groundSpawns = append(groundSpawns, gs)
|
||||
|
||||
return nil
|
||||
}, zoneID)
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query groundspawns: %w", err)
|
||||
@ -197,9 +228,18 @@ func (da *DatabaseAdapter) LoadAllGroundSpawns() ([]*GroundSpawn, error) {
|
||||
|
||||
// DeleteGroundSpawn deletes a ground spawn from the database
|
||||
func (da *DatabaseAdapter) DeleteGroundSpawn(id int32) error {
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
query := `DELETE FROM groundspawns WHERE id = ?`
|
||||
|
||||
err := da.db.Exec(query, id)
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{id},
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete ground spawn %d: %w", id, err)
|
||||
}
|
||||
@ -209,6 +249,13 @@ func (da *DatabaseAdapter) DeleteGroundSpawn(id int32) error {
|
||||
|
||||
// LoadPlayerHarvestStatistics loads harvest statistics for a player
|
||||
func (da *DatabaseAdapter) LoadPlayerHarvestStatistics(playerID int32) (map[string]int64, error) {
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
query := `
|
||||
SELECT skill_name, harvest_count
|
||||
FROM player_harvest_stats
|
||||
@ -216,15 +263,15 @@ func (da *DatabaseAdapter) LoadPlayerHarvestStatistics(playerID int32) (map[stri
|
||||
`
|
||||
|
||||
stats := make(map[string]int64)
|
||||
|
||||
err := da.db.Query(query, func(row *database.Row) error {
|
||||
skillName := row.Text(0)
|
||||
harvestCount := row.Int64(1)
|
||||
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{playerID},
|
||||
ResultFunc: func(stmt *sqlite.Stmt) error {
|
||||
skillName := stmt.ColumnText(0)
|
||||
harvestCount := stmt.ColumnInt64(1)
|
||||
stats[skillName] = harvestCount
|
||||
|
||||
return nil
|
||||
}, playerID)
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query player harvest stats: %w", err)
|
||||
@ -235,15 +282,125 @@ func (da *DatabaseAdapter) LoadPlayerHarvestStatistics(playerID int32) (map[stri
|
||||
|
||||
// SavePlayerHarvestStatistic saves a player's harvest statistic
|
||||
func (da *DatabaseAdapter) SavePlayerHarvestStatistic(playerID int32, skillName string, count int64) error {
|
||||
ctx := context.Background()
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
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)
|
||||
err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
|
||||
Args: []any{playerID, skillName, count},
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save player harvest stat: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnsureGroundSpawnTables creates the necessary database tables if they don't exist
|
||||
func (da *DatabaseAdapter) EnsureGroundSpawnTables(ctx context.Context) error {
|
||||
conn, err := da.pool.Take(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get database connection: %w", err)
|
||||
}
|
||||
defer da.pool.Put(conn)
|
||||
|
||||
// Create groundspawns table
|
||||
createGroundSpawnsTable := `
|
||||
CREATE TABLE IF NOT EXISTS groundspawns (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
x REAL NOT NULL,
|
||||
y REAL NOT NULL,
|
||||
z REAL NOT NULL,
|
||||
heading REAL NOT NULL,
|
||||
respawn_timer INTEGER NOT NULL DEFAULT 300,
|
||||
collection_skill TEXT NOT NULL,
|
||||
number_harvests INTEGER NOT NULL DEFAULT 1,
|
||||
attempts_per_harvest INTEGER NOT NULL DEFAULT 1,
|
||||
groundspawn_entry_id INTEGER NOT NULL,
|
||||
randomize_heading INTEGER NOT NULL DEFAULT 0,
|
||||
zone_id INTEGER NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`
|
||||
|
||||
// Create groundspawn_entries table
|
||||
createGroundSpawnEntriesTable := `
|
||||
CREATE TABLE IF NOT EXISTS groundspawn_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
groundspawn_id INTEGER NOT NULL,
|
||||
min_skill_level INTEGER NOT NULL DEFAULT 0,
|
||||
min_adventure_level INTEGER NOT NULL DEFAULT 0,
|
||||
bonus_table INTEGER NOT NULL DEFAULT 0,
|
||||
harvest_1 REAL NOT NULL DEFAULT 0.0,
|
||||
harvest_3 REAL NOT NULL DEFAULT 0.0,
|
||||
harvest_5 REAL NOT NULL DEFAULT 0.0,
|
||||
harvest_imbue REAL NOT NULL DEFAULT 0.0,
|
||||
harvest_rare REAL NOT NULL DEFAULT 0.0,
|
||||
harvest_10 REAL NOT NULL DEFAULT 0.0,
|
||||
harvest_coin REAL NOT NULL DEFAULT 0.0
|
||||
)
|
||||
`
|
||||
|
||||
// Create groundspawn_items table
|
||||
createGroundSpawnItemsTable := `
|
||||
CREATE TABLE IF NOT EXISTS groundspawn_items (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
groundspawn_id INTEGER NOT NULL,
|
||||
item_id INTEGER NOT NULL,
|
||||
is_rare INTEGER NOT NULL DEFAULT 0,
|
||||
grid_id INTEGER NOT NULL DEFAULT 0,
|
||||
quantity INTEGER NOT NULL DEFAULT 1
|
||||
)
|
||||
`
|
||||
|
||||
// Create player_harvest_stats table
|
||||
createPlayerHarvestStatsTable := `
|
||||
CREATE TABLE IF NOT EXISTS player_harvest_stats (
|
||||
player_id INTEGER NOT NULL,
|
||||
skill_name TEXT NOT NULL,
|
||||
harvest_count INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (player_id, skill_name)
|
||||
)
|
||||
`
|
||||
|
||||
// Execute table creation statements
|
||||
tables := []string{
|
||||
createGroundSpawnsTable,
|
||||
createGroundSpawnEntriesTable,
|
||||
createGroundSpawnItemsTable,
|
||||
createPlayerHarvestStatsTable,
|
||||
}
|
||||
|
||||
for _, tableSQL := range tables {
|
||||
if err := sqlitex.Execute(conn, tableSQL, nil); err != nil {
|
||||
return fmt.Errorf("failed to create table: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create indexes
|
||||
indexes := []string{
|
||||
`CREATE INDEX IF NOT EXISTS idx_groundspawn_entries_groundspawn_id ON groundspawn_entries(groundspawn_id)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_groundspawn_items_groundspawn_id ON groundspawn_items(groundspawn_id)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_groundspawns_zone_id ON groundspawns(zone_id)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_player_harvest_stats_player_id ON player_harvest_stats(player_id)`,
|
||||
}
|
||||
|
||||
for _, indexSQL := range indexes {
|
||||
if err := sqlitex.Execute(conn, indexSQL, nil); err != nil {
|
||||
return fmt.Errorf("failed to create index: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user