264 lines
8.1 KiB
Go
264 lines
8.1 KiB
Go
package factions
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"eq2emu/internal/database"
|
|
)
|
|
|
|
// DatabaseAdapter implements the factions.Database interface using our database wrapper
|
|
type DatabaseAdapter struct {
|
|
db *database.DB
|
|
}
|
|
|
|
// NewDatabaseAdapter creates a new database adapter for factions
|
|
func NewDatabaseAdapter(db *database.DB) *DatabaseAdapter {
|
|
return &DatabaseAdapter{db: db}
|
|
}
|
|
|
|
// LoadAllFactions loads all factions from the database
|
|
func (da *DatabaseAdapter) LoadAllFactions() ([]*Faction, error) {
|
|
// Create factions table if it doesn't exist
|
|
if err := da.db.Exec(`
|
|
CREATE TABLE IF NOT EXISTS factions (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
type TEXT,
|
|
description TEXT,
|
|
negative_change INTEGER DEFAULT 0,
|
|
positive_change INTEGER DEFAULT 0,
|
|
default_value INTEGER DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
`); err != nil {
|
|
return nil, fmt.Errorf("failed to create factions table: %w", err)
|
|
}
|
|
|
|
var factions []*Faction
|
|
err := da.db.Query("SELECT id, name, type, description, negative_change, positive_change, default_value FROM factions", func(row *database.Row) error {
|
|
faction := &Faction{
|
|
ID: int32(row.Int64(0)),
|
|
Name: row.Text(1),
|
|
Type: row.Text(2),
|
|
Description: row.Text(3),
|
|
NegativeChange: int16(row.Int64(4)),
|
|
PositiveChange: int16(row.Int64(5)),
|
|
DefaultValue: int32(row.Int64(6)),
|
|
}
|
|
factions = append(factions, faction)
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load factions: %w", err)
|
|
}
|
|
|
|
return factions, nil
|
|
}
|
|
|
|
// SaveFaction saves a faction to the database
|
|
func (da *DatabaseAdapter) SaveFaction(faction *Faction) error {
|
|
if faction == nil {
|
|
return fmt.Errorf("faction is nil")
|
|
}
|
|
|
|
// Use INSERT OR REPLACE to handle both insert and update
|
|
err := da.db.Exec(`
|
|
INSERT OR REPLACE INTO factions (id, name, type, description, negative_change, positive_change, default_value, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
`, faction.ID, faction.Name, faction.Type, faction.Description,
|
|
faction.NegativeChange, faction.PositiveChange, faction.DefaultValue, time.Now().Unix())
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to save faction %d: %w", faction.ID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteFaction deletes a faction from the database
|
|
func (da *DatabaseAdapter) DeleteFaction(factionID int32) error {
|
|
err := da.db.Exec("DELETE FROM factions WHERE id = ?", factionID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete faction %d: %w", factionID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadHostileFactionRelations loads all hostile faction relations
|
|
func (da *DatabaseAdapter) LoadHostileFactionRelations() ([]*FactionRelation, error) {
|
|
// Create faction_relations table if it doesn't exist
|
|
if err := da.db.Exec(`
|
|
CREATE TABLE IF NOT EXISTS faction_relations (
|
|
faction_id INTEGER NOT NULL,
|
|
related_faction_id INTEGER NOT NULL,
|
|
is_hostile INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (faction_id, related_faction_id),
|
|
FOREIGN KEY (faction_id) REFERENCES factions(id),
|
|
FOREIGN KEY (related_faction_id) REFERENCES factions(id)
|
|
)
|
|
`); err != nil {
|
|
return nil, fmt.Errorf("failed to create faction_relations table: %w", err)
|
|
}
|
|
|
|
var relations []*FactionRelation
|
|
err := da.db.Query("SELECT faction_id, related_faction_id FROM faction_relations WHERE is_hostile = 1",
|
|
func(row *database.Row) error {
|
|
relation := &FactionRelation{
|
|
FactionID: int32(row.Int64(0)),
|
|
HostileFactionID: int32(row.Int64(1)),
|
|
}
|
|
relations = append(relations, relation)
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load hostile faction relations: %w", err)
|
|
}
|
|
|
|
return relations, nil
|
|
}
|
|
|
|
// LoadFriendlyFactionRelations loads all friendly faction relations
|
|
func (da *DatabaseAdapter) LoadFriendlyFactionRelations() ([]*FactionRelation, error) {
|
|
var relations []*FactionRelation
|
|
err := da.db.Query("SELECT faction_id, related_faction_id FROM faction_relations WHERE is_hostile = 0",
|
|
func(row *database.Row) error {
|
|
relation := &FactionRelation{
|
|
FactionID: int32(row.Int64(0)),
|
|
FriendlyFactionID: int32(row.Int64(1)),
|
|
}
|
|
relations = append(relations, relation)
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load friendly faction relations: %w", err)
|
|
}
|
|
|
|
return relations, nil
|
|
}
|
|
|
|
// SaveFactionRelation saves a faction relation to the database
|
|
func (da *DatabaseAdapter) SaveFactionRelation(relation *FactionRelation) error {
|
|
if relation == nil {
|
|
return fmt.Errorf("faction relation is nil")
|
|
}
|
|
|
|
var relatedFactionID int32
|
|
var isHostile int
|
|
|
|
if relation.HostileFactionID != 0 {
|
|
relatedFactionID = relation.HostileFactionID
|
|
isHostile = 1
|
|
} else if relation.FriendlyFactionID != 0 {
|
|
relatedFactionID = relation.FriendlyFactionID
|
|
isHostile = 0
|
|
} else {
|
|
return fmt.Errorf("faction relation has no related faction ID")
|
|
}
|
|
|
|
err := da.db.Exec(`
|
|
INSERT OR REPLACE INTO faction_relations (faction_id, related_faction_id, is_hostile)
|
|
VALUES (?, ?, ?)
|
|
`, relation.FactionID, relatedFactionID, isHostile)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to save faction relation %d -> %d: %w",
|
|
relation.FactionID, relatedFactionID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteFactionRelation deletes a faction relation from the database
|
|
func (da *DatabaseAdapter) DeleteFactionRelation(factionID, relatedFactionID int32, isHostile bool) error {
|
|
hostileFlag := 0
|
|
if isHostile {
|
|
hostileFlag = 1
|
|
}
|
|
|
|
err := da.db.Exec("DELETE FROM faction_relations WHERE faction_id = ? AND related_faction_id = ? AND is_hostile = ?",
|
|
factionID, relatedFactionID, hostileFlag)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete faction relation %d -> %d: %w",
|
|
factionID, relatedFactionID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadPlayerFactions loads player faction values from the database
|
|
func (da *DatabaseAdapter) LoadPlayerFactions(playerID int32) (map[int32]int32, error) {
|
|
// Create player_factions table if it doesn't exist
|
|
if err := da.db.Exec(`
|
|
CREATE TABLE IF NOT EXISTS player_factions (
|
|
player_id INTEGER NOT NULL,
|
|
faction_id INTEGER NOT NULL,
|
|
faction_value INTEGER NOT NULL DEFAULT 0,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (player_id, faction_id),
|
|
FOREIGN KEY (faction_id) REFERENCES factions(id)
|
|
)
|
|
`); err != nil {
|
|
return nil, fmt.Errorf("failed to create player_factions table: %w", err)
|
|
}
|
|
|
|
factionValues := make(map[int32]int32)
|
|
err := da.db.Query("SELECT faction_id, faction_value FROM player_factions WHERE player_id = ?",
|
|
func(row *database.Row) error {
|
|
factionID := int32(row.Int64(0))
|
|
factionValue := int32(row.Int64(1))
|
|
factionValues[factionID] = factionValue
|
|
return nil
|
|
}, playerID)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load player factions for player %d: %w", playerID, err)
|
|
}
|
|
|
|
return factionValues, nil
|
|
}
|
|
|
|
// SavePlayerFaction saves a player's faction value to the database
|
|
func (da *DatabaseAdapter) SavePlayerFaction(playerID, factionID, factionValue int32) error {
|
|
err := da.db.Exec(`
|
|
INSERT OR REPLACE INTO player_factions (player_id, faction_id, faction_value, updated_at)
|
|
VALUES (?, ?, ?, ?)
|
|
`, playerID, factionID, factionValue, time.Now().Unix())
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to save player faction %d/%d: %w", playerID, factionID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SaveAllPlayerFactions saves all faction values for a player
|
|
func (da *DatabaseAdapter) SaveAllPlayerFactions(playerID int32, factionValues map[int32]int32) error {
|
|
return da.db.Transaction(func(txDB *database.DB) error {
|
|
// Clear existing faction values for this player
|
|
if err := txDB.Exec("DELETE FROM player_factions WHERE player_id = ?", playerID); err != nil {
|
|
return fmt.Errorf("failed to clear player factions: %w", err)
|
|
}
|
|
|
|
// Insert all current faction values
|
|
for factionID, factionValue := range factionValues {
|
|
err := txDB.Exec(`
|
|
INSERT INTO player_factions (player_id, faction_id, faction_value, updated_at)
|
|
VALUES (?, ?, ?, ?)
|
|
`, playerID, factionID, factionValue, time.Now().Unix())
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to insert player faction %d/%d: %w", playerID, factionID, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
} |