Nethack Launcher
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

126 lines
3.3 KiB

package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"gopkg.in/redis.v5"
)
func recoverSave(redisClient *redis.Client, username string) {
// if no statefile exist, exit early as we cannot recover
matches, _ := filepath.Glob(fmt.Sprintf("%s/user/%s/*lock*", config.NethackLauncher.HackDir, username))
if matches == nil {
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
println(" The dungeon crumbles around you, darkness remains...")
println(" Godspeed adventurer..")
println("")
println(" No statefiles exist. (press enter to return)")
println("")
fmt.Printf(">> ")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if scanner.Text() == "" {
printUserScreen(redisClient, username)
}
}
}
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
println(" Recover utility.")
println("")
// check if dir is empty
isEmpty, _ := checkDir(fmt.Sprintf("%s/user/%s/save/", config.NethackLauncher.HackDir, username))
if !isEmpty {
// save file exists, overwrite?
println(" Save file already exists!")
println(" Overwrite? (y/n)")
println("")
fmt.Printf(">> ")
} else {
println(" Attempt to recover statefile? (y/n)")
println("")
fmt.Printf(">> ")
}
// disable input buffering
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
// do not display entered characters on the screen
exec.Command("stty", "-F", "/dev/tty", "-echo").Run()
var b []byte = make([]byte, 1)
for {
os.Stdin.Read(b)
switch string(b) {
case "n":
clearScreen()
printUserScreen(redisClient, username)
case "y":
// set user path to save file candidates
userPath := fmt.Sprintf("%s/user/%s/", config.NethackLauncher.HackDir, username)
// read in all files
candidates, err := ioutil.ReadDir(userPath)
if err != nil {
fmt.Println(err)
}
var newestFile string
var newestTime int64 = 0
for _, f := range candidates {
// loop through save file candidates
if strings.Contains(f.Name(), "lock") {
fi, err := os.Stat(userPath + f.Name())
if err != nil {
fmt.Println(err)
}
currTime := fi.ModTime().Unix()
if currTime > newestTime {
newestTime = currTime
newestFile = f.Name()
}
}
}
// get prefix for latest file
latestFile := strings.Split(newestFile, ".")
// run recover on file
out, err := exec.Command(config.NethackLauncher.RecoverBinary, "-d", fmt.Sprintf("%s/user/%s", config.NethackLauncher.HackDir, username), latestFile[0]).Output()
if err != nil {
fmt.Println(out)
panic(err)
}
// make sure save file exists before removing the extra locks
isEmpty, _ = checkDir(fmt.Sprintf("%s/user/%s/save/", config.NethackLauncher.HackDir, username))
if !isEmpty {
// save file made it, clean up old cruft
files, err := filepath.Glob(fmt.Sprintf("%s/*lock*", userPath))
if err != nil {
panic(err)
}
for _, f := range files {
if err := os.Remove(f); err != nil {
panic(err)
}
}
// alert user that the save file was recovered
println("")
println(" Statefile was recovered successfully! (press enter to return)")
fmt.Printf(">> ")
}
case "\n":
clearScreen()
printUserScreen(redisClient, username)
default:
}
}
}