package factions import ( "fmt" "eq2emu/internal/database" ) // LoadAllFactions loads all factions from the database func LoadAllFactions(db *database.Database) ([]*Faction, error) { // Create factions table if it doesn't exist _, err := 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 ) `) if err != nil { return nil, fmt.Errorf("failed to create factions table: %w", err) } rows, err := db.Query("SELECT id, name, type, description, negative_change, positive_change, default_value FROM factions") if err != nil { return nil, fmt.Errorf("failed to load factions: %w", err) } defer rows.Close() var factions []*Faction for rows.Next() { faction := &Faction{ db: db, isNew: false, } err := rows.Scan(&faction.ID, &faction.Name, &faction.Type, &faction.Description, &faction.NegativeChange, &faction.PositiveChange, &faction.DefaultValue) if err != nil { return nil, fmt.Errorf("failed to scan faction: %w", err) } factions = append(factions, faction) } if err = rows.Err(); err != nil { return nil, fmt.Errorf("error iterating factions: %w", err) } return factions, nil } // LoadFactionRelations loads faction relationships from the database func LoadFactionRelations(db *database.Database) (map[int32][]int32, map[int32][]int32, error) { // Create faction_relations table if it doesn't exist _, err := 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, PRIMARY KEY (faction_id, related_faction_id), FOREIGN KEY (faction_id) REFERENCES factions(id), FOREIGN KEY (related_faction_id) REFERENCES factions(id) ) `) if err != nil { return nil, nil, fmt.Errorf("failed to create faction_relations table: %w", err) } hostile := make(map[int32][]int32) friendly := make(map[int32][]int32) rows, err := db.Query("SELECT faction_id, related_faction_id, is_hostile FROM faction_relations") if err != nil { return nil, nil, fmt.Errorf("failed to load faction relations: %w", err) } defer rows.Close() for rows.Next() { var factionID, relatedID int32 var isHostile bool if err := rows.Scan(&factionID, &relatedID, &isHostile); err != nil { return nil, nil, fmt.Errorf("failed to scan faction relation: %w", err) } if isHostile { hostile[factionID] = append(hostile[factionID], relatedID) } else { friendly[factionID] = append(friendly[factionID], relatedID) } } if err = rows.Err(); err != nil { return nil, nil, fmt.Errorf("error iterating faction relations: %w", err) } return hostile, friendly, nil } // SaveFactionRelation saves a faction relationship to the database func SaveFactionRelation(db *database.Database, factionID, relatedFactionID int32, isHostile bool) error { hostileFlag := 0 if isHostile { hostileFlag = 1 } _, err := db.Exec(` INSERT OR REPLACE INTO faction_relations (faction_id, related_faction_id, is_hostile) VALUES (?, ?, ?) `, factionID, relatedFactionID, hostileFlag) if err != nil { return fmt.Errorf("failed to save faction relation %d -> %d: %w", factionID, relatedFactionID, err) } return nil } // DeleteFactionRelation deletes a faction relationship from the database func DeleteFactionRelation(db *database.Database, factionID, relatedFactionID int32, isHostile bool) error { hostileFlag := 0 if isHostile { hostileFlag = 1 } _, err := 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 LoadPlayerFactions(db *database.Database, playerID int32) (map[int32]int32, error) { // Create player_factions table if it doesn't exist _, err := 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, PRIMARY KEY (player_id, faction_id), FOREIGN KEY (faction_id) REFERENCES factions(id) ) `) if err != nil { return nil, fmt.Errorf("failed to create player_factions table: %w", err) } factionValues := make(map[int32]int32) rows, err := db.Query("SELECT faction_id, faction_value FROM player_factions WHERE player_id = ?", playerID) if err != nil { return nil, fmt.Errorf("failed to load player factions for player %d: %w", playerID, err) } defer rows.Close() for rows.Next() { var factionID, factionValue int32 if err := rows.Scan(&factionID, &factionValue); err != nil { return nil, fmt.Errorf("failed to scan player faction: %w", err) } factionValues[factionID] = factionValue } if err = rows.Err(); err != nil { return nil, fmt.Errorf("error iterating player factions: %w", err) } return factionValues, nil } // SavePlayerFaction saves a player's faction value to the database func SavePlayerFaction(db *database.Database, playerID, factionID, factionValue int32) error { _, err := db.Exec(` INSERT OR REPLACE INTO player_factions (player_id, faction_id, faction_value) VALUES (?, ?, ?) `, playerID, factionID, factionValue) 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 SaveAllPlayerFactions(db *database.Database, playerID int32, factionValues map[int32]int32) error { tx, err := db.Begin() if err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } defer tx.Rollback() // Clear existing faction values for this player _, err = tx.Exec("DELETE FROM player_factions WHERE player_id = ?", playerID) if err != nil { return fmt.Errorf("failed to clear player factions: %w", err) } // Insert all current faction values for factionID, factionValue := range factionValues { _, err = tx.Exec(` INSERT INTO player_factions (player_id, faction_id, faction_value) VALUES (?, ?, ?) `, playerID, factionID, factionValue) if err != nil { return fmt.Errorf("failed to insert player faction %d/%d: %w", playerID, factionID, err) } } return tx.Commit() }