package main import ( "encoding/json" "errors" "os" "path/filepath" ) // ПРИМЕЧАНИЕ: сохранение реализовано только для этой игры — она // единственная в коллекции без чёткого конца партии, поэтому жалко // сбрасывать прогресс при каждом выходе в меню. Остальные 8 игр // коллекции по-прежнему не сохраняются между запусками — обычно в // них и не нужно (партия проходится за один присест). // ErrCorpseStarchNoSave возвращается LoadCorpseStarchGame, если // файл сохранения не найден (новая партия должна начаться с нуля). var ErrCorpseStarchNoSave = errors.New("файл сохранения не найден") // corpseStarchSavePath возвращает путь к файлу сохранения в // пользовательской конфигурационной директории (например, // ~/.config/go-games-collection/corpsestarch_save.json на Linux). func corpseStarchSavePath() (string, error) { dir, err := os.UserConfigDir() if err != nil { return "", err } return filepath.Join(dir, "go-games-collection", "corpsestarch_save.json"), nil } // SaveCorpseStarchGame сохраняет текущее состояние партии на диск, // создавая директорию сохранения при необходимости. func SaveCorpseStarchGame(g *CorpseStarchGameState) error { path, err := corpseStarchSavePath() if err != nil { return err } if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return err } data, err := json.MarshalIndent(g, "", " ") if err != nil { return err } return os.WriteFile(path, data, 0o644) } // LoadCorpseStarchGame загружает сохранённую партию с диска. // Возвращает ErrCorpseStarchNoSave, если файла сохранения нет — // вызывающий код должен в этом случае начать новую партию. func LoadCorpseStarchGame() (*CorpseStarchGameState, error) { path, err := corpseStarchSavePath() if err != nil { return nil, err } data, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return nil, ErrCorpseStarchNoSave } return nil, err } var g CorpseStarchGameState if err := json.Unmarshal(data, &g); err != nil { return nil, err } if len(g.ServitorCounts) < len(corpseStarchServitorDefs) { grown := make([]int, len(corpseStarchServitorDefs)) copy(grown, g.ServitorCounts) g.ServitorCounts = grown } if g.BonusMultiplier == 0 { g.BonusMultiplier = 1 } return &g, nil } // DeleteCorpseStarchSave удаляет файл сохранения, если он есть // (используется для явного сброса прогресса). Отсутствие файла не // считается ошибкой. func DeleteCorpseStarchSave() error { path, err := corpseStarchSavePath() if err != nil { return err } err = os.Remove(path) if err != nil && !os.IsNotExist(err) { return err } return nil }