Files
LilGuy/internal/save/save.go

181 lines
3.1 KiB
Go

package save
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/BurntSushi/toml"
)
const (
dataFile = "data.toml"
)
// Save file structure
type Data struct {
Settings Settings `toml:"settings"`
GameState GameState `toml:"game_state"`
}
type Settings struct {
FPSMonitor bool `toml:"fps_monitor"`
FPSCap string `toml:"fps_cap"`
}
type GameState struct {
HasSave bool `toml:"has_save"`
SavedAt time.Time `toml:"saved_at"`
HeroX float64 `toml:"hero_x"`
HeroY float64 `toml:"hero_y"`
HeroStamina float64 `toml:"hero_stamina"`
PlayTimeMS int64 `toml:"play_time_ms"`
}
// Save manager
type Manager struct {
dataPath string
}
func NewManager() (*Manager, error) {
exePath, err := os.Executable()
if err != nil {
return nil, fmt.Errorf("failed to get executable path: %w", err)
}
exeDir := filepath.Dir(exePath)
return &Manager{
dataPath: filepath.Join(exeDir, dataFile),
}, nil
}
// Data operations
func (m *Manager) LoadData() (*Data, error) {
if _, err := os.Stat(m.dataPath); os.IsNotExist(err) {
return &Data{
Settings: Settings{
FPSMonitor: false,
FPSCap: "60",
},
GameState: GameState{
HasSave: false,
},
}, nil
}
var data Data
if _, err := toml.DecodeFile(m.dataPath, &data); err != nil {
return nil, fmt.Errorf("failed to parse data file: %w", err)
}
return &data, nil
}
func (m *Manager) SaveData(data *Data) error {
file, err := os.Create(m.dataPath)
if err != nil {
return fmt.Errorf("failed to create data file: %w", err)
}
defer file.Close()
encoder := toml.NewEncoder(file)
if err := encoder.Encode(data); err != nil {
return fmt.Errorf("failed to write data file: %w", err)
}
return nil
}
// Settings operations
func (m *Manager) LoadSettings() (*Settings, error) {
data, err := m.LoadData()
if err != nil {
return nil, err
}
return &data.Settings, nil
}
func (m *Manager) SaveSettings(settings *Settings) error {
data, err := m.LoadData()
if err != nil {
data = &Data{
Settings: *settings,
GameState: GameState{
HasSave: false,
},
}
} else {
data.Settings = *settings
}
return m.SaveData(data)
}
// Game state operations
func (m *Manager) LoadGameState() (*GameState, error) {
data, err := m.LoadData()
if err != nil {
return nil, err
}
if !data.GameState.HasSave {
return nil, nil
}
return &data.GameState, nil
}
func (m *Manager) SaveGameState(state *GameState) error {
data, err := m.LoadData()
if err != nil {
data = &Data{
Settings: Settings{
FPSMonitor: false,
FPSCap: "60",
},
GameState: *state,
}
} else {
data.GameState = *state
}
data.GameState.HasSave = true
data.GameState.SavedAt = time.Now()
return m.SaveData(data)
}
func (m *Manager) HasSavedGame() bool {
data, err := m.LoadData()
if err != nil {
return false
}
return data.GameState.HasSave
}
func (m *Manager) DeleteGameState() error {
data, err := m.LoadData()
if err != nil {
return err
}
data.GameState = GameState{
HasSave: false,
}
return m.SaveData(data)
}
// Utilities
func (m *Manager) GetSaveFilePath() string {
return m.dataPath
}