eq2go/internal/appearances/appearance.go

190 lines
4.8 KiB
Go

package appearances
import (
"fmt"
"eq2emu/internal/database"
)
// Appearance represents a single appearance with ID, name, and client version requirements
type Appearance struct {
ID int32 `json:"id"` // Appearance ID
Name string `json:"name"` // Appearance name
MinClient int16 `json:"min_client"` // Minimum client version required
db *database.Database `json:"-"` // Database connection
isNew bool `json:"-"` // Whether this is a new appearance
}
// New creates a new appearance with the given database
func New(db *database.Database) *Appearance {
return &Appearance{
db: db,
isNew: true,
}
}
// NewWithData creates a new appearance with data
func NewWithData(id int32, name string, minClientVersion int16, db *database.Database) *Appearance {
return &Appearance{
ID: id,
Name: name,
MinClient: minClientVersion,
db: db,
isNew: true,
}
}
// Load loads an appearance by ID from the database
func Load(db *database.Database, id int32) (*Appearance, error) {
appearance := &Appearance{
db: db,
isNew: false,
}
query := `SELECT appearance_id, name, min_client_version FROM appearances WHERE appearance_id = ?`
row := db.QueryRow(query, id)
err := row.Scan(&appearance.ID, &appearance.Name, &appearance.MinClient)
if err != nil {
return nil, fmt.Errorf("failed to load appearance %d: %w", id, err)
}
return appearance, nil
}
// GetID returns the appearance ID (implements Identifiable interface)
func (a *Appearance) GetID() int32 {
return a.ID
}
// GetName returns the appearance name
func (a *Appearance) GetName() string {
return a.Name
}
// GetMinClientVersion returns the minimum client version required
func (a *Appearance) GetMinClientVersion() int16 {
return a.MinClient
}
// GetNameString returns the name as a string (alias for GetName for C++ compatibility)
func (a *Appearance) GetNameString() string {
return a.Name
}
// SetName sets the appearance name
func (a *Appearance) SetName(name string) {
a.Name = name
}
// SetMinClientVersion sets the minimum client version
func (a *Appearance) SetMinClientVersion(version int16) {
a.MinClient = version
}
// IsCompatibleWithClient returns true if the appearance is compatible with the given client version
func (a *Appearance) IsCompatibleWithClient(clientVersion int16) bool {
return clientVersion >= a.MinClient
}
// IsNew returns true if this is a new appearance not yet saved to database
func (a *Appearance) IsNew() bool {
return a.isNew
}
// Save saves the appearance to the database
func (a *Appearance) Save() error {
if a.db == nil {
return fmt.Errorf("no database connection available")
}
if a.isNew {
return a.insert()
}
return a.update()
}
// Delete removes the appearance from the database
func (a *Appearance) Delete() error {
if a.db == nil {
return fmt.Errorf("no database connection available")
}
if a.isNew {
return fmt.Errorf("cannot delete unsaved appearance")
}
query := `DELETE FROM appearances WHERE appearance_id = ?`
_, err := a.db.Exec(query, a.ID)
if err != nil {
return fmt.Errorf("failed to delete appearance %d: %w", a.ID, err)
}
return nil
}
// Reload reloads the appearance data from the database
func (a *Appearance) Reload() error {
if a.db == nil {
return fmt.Errorf("no database connection available")
}
if a.isNew {
return fmt.Errorf("cannot reload unsaved appearance")
}
query := `SELECT name, min_client_version FROM appearances WHERE appearance_id = ?`
row := a.db.QueryRow(query, a.ID)
err := row.Scan(&a.Name, &a.MinClient)
if err != nil {
return fmt.Errorf("failed to reload appearance %d: %w", a.ID, err)
}
return nil
}
// Clone creates a copy of the appearance
func (a *Appearance) Clone() *Appearance {
return &Appearance{
ID: a.ID,
Name: a.Name,
MinClient: a.MinClient,
db: a.db,
isNew: true, // Clone is always new
}
}
// insert inserts a new appearance into the database
func (a *Appearance) insert() error {
query := `INSERT INTO appearances (appearance_id, name, min_client_version) VALUES (?, ?, ?)`
_, err := a.db.Exec(query, a.ID, a.Name, a.MinClient)
if err != nil {
return fmt.Errorf("failed to insert appearance: %w", err)
}
a.isNew = false
return nil
}
// update updates an existing appearance in the database
func (a *Appearance) update() error {
query := `UPDATE appearances SET name = ?, min_client_version = ? WHERE appearance_id = ?`
result, err := a.db.Exec(query, a.Name, a.MinClient, a.ID)
if err != nil {
return fmt.Errorf("failed to update appearance: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get rows affected: %w", err)
}
if rowsAffected == 0 {
return fmt.Errorf("appearance %d not found for update", a.ID)
}
return nil
}