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.
 
 

139 lines
3.9 KiB

package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)
func runGame(username, timestamp string) {
// check if a lockfile exists
matches, _ := filepath.Glob(fmt.Sprintf("%s/user/%s/*lock*", config.NethackLauncher.HackDir, username))
if matches != nil {
clearScreen()
runtimeRecover(username)
}
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
clearScreen()
// put together users home dir
homeDir := fmt.Sprintf("%s/user/%s/", config.NethackLauncher.HackDir, username)
ttyrecPath := fmt.Sprintf("%s/user/%s/ttyrec/%s.ttyrec", config.NethackLauncher.HackDir, username, timestamp)
nh := exec.Command("ttyrec", "-f", ttyrecPath, "--", "nethack")
nh.Env = os.Environ()
nh.Env = append(nh.Env, fmt.Sprintf("HOME=%s", homeDir))
nh.Env = append(nh.Env, fmt.Sprintf("USER=%s", username))
nh.Env = append(nh.Env, fmt.Sprintf("NETHACKDIR=%s/user/%s", config.NethackLauncher.HackDir, username))
nh.Stdout = os.Stdout
nh.Stdin = os.Stdin
nh.Stderr = os.Stderr
err := nh.Run()
if err != nil {
fmt.Print(err)
}
exec.Command("exit").Run()
wg.Done()
}
func runtimeRecover(username string) {
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
println(" Existing lockfile found.")
println(" This generally means that your last session crashed")
println(" or you are logged in more than once.")
println("")
println(" What would you like to do with the lockfile?")
println(" d) delete it and contiue to a new adventure")
println(" r) recover it and continue your last adventure")
println(" n) nothing at all and get this prompt again next time")
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()
return
case "r":
// 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(">> ")
}
return
case "d":
// remove all lockfiles and continue
userPath := fmt.Sprintf("%s/user/%s/", config.NethackLauncher.HackDir, username)
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)
}
}
return
}
}
}