eq2go/internal/factions/database.go

220 lines
6.4 KiB
Go

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()
}