100 lines
3.1 KiB
Go
100 lines
3.1 KiB
Go
package main
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"os"
|
||
"path/filepath"
|
||
)
|
||
|
||
// ПРИМЕЧАНИЕ: как и "Трупные батончики", "Странник" сохраняется на
|
||
// диск — это открытая, долгоиграющая карьера без фиксированного
|
||
// конца партии, и жалко было бы сбрасывать прогресс при каждом
|
||
// выходе в меню. Остальные игры коллекции по-прежнему не сохраняются
|
||
// между запусками.
|
||
|
||
var ErrWayfarerNoSave = errors.New("файл сохранения не найден")
|
||
|
||
func wayfarerSavePath() (string, error) {
|
||
dir, err := os.UserConfigDir()
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return filepath.Join(dir, "go-games-collection", "wayfarer_save.json"), nil
|
||
}
|
||
|
||
// SaveWayfarerShip сохраняет текущее состояние карьеры на диск.
|
||
func SaveWayfarerShip(s *WayfarerShip) error {
|
||
path, err := wayfarerSavePath()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||
return err
|
||
}
|
||
data, err := json.MarshalIndent(s, "", " ")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return os.WriteFile(path, data, 0o644)
|
||
}
|
||
|
||
// LoadWayfarerShip загружает сохранённую карьеру с диска. Возвращает
|
||
// ErrWayfarerNoSave, если файла нет — вызывающий код должен в этом
|
||
// случае начать новую карьеру.
|
||
func LoadWayfarerShip() (*WayfarerShip, error) {
|
||
path, err := wayfarerSavePath()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
data, err := os.ReadFile(path)
|
||
if err != nil {
|
||
if os.IsNotExist(err) {
|
||
return nil, ErrWayfarerNoSave
|
||
}
|
||
return nil, err
|
||
}
|
||
var s WayfarerShip
|
||
if err := json.Unmarshal(data, &s); err != nil {
|
||
return nil, err
|
||
}
|
||
if s.Equipment == nil {
|
||
s.Equipment = map[WayfarerEquipment]bool{}
|
||
}
|
||
if s.Visited == nil {
|
||
s.Visited = map[WayfarerSystemID]bool{}
|
||
}
|
||
if s.CompletedQuests == nil {
|
||
s.CompletedQuests = map[string]bool{}
|
||
}
|
||
if s.FailedQuests == nil {
|
||
s.FailedQuests = map[string]bool{}
|
||
}
|
||
if s.MissileCapacity == 0 {
|
||
// поле появилось уже после того, как некоторые сохранения были
|
||
// созданы — без этой миграции у них "нет свободных слотов"
|
||
// навсегда, хотя ракет на борту нет вовсе (0 >= 0)
|
||
s.MissileCapacity = 2
|
||
}
|
||
if len(s.Cargo) < len(WayfarerCommodities) {
|
||
grown := make([]int, len(WayfarerCommodities))
|
||
copy(grown, s.Cargo)
|
||
s.Cargo = grown
|
||
}
|
||
return &s, nil
|
||
}
|
||
|
||
// DeleteWayfarerSave удаляет файл сохранения (используется при
|
||
// гибели корабля без спасательной капсулы — карьера окончена
|
||
// безвозвратно, начинать заново нужно с чистого листа).
|
||
func DeleteWayfarerSave() error {
|
||
path, err := wayfarerSavePath()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
err = os.Remove(path)
|
||
if err != nil && !os.IsNotExist(err) {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|