Compare commits

...

17 Commits

Author SHA1 Message Date
Matthew Faltys acd35ba734 Merge pull request 'Update develop with new SOTW build' (#1) from feature/sotw into develop 2 years ago
Matthew Faltys b6f0768971 Update to SOTW 1.2.2 4 years ago
Matthew Faltys 7e2bf9949e Add ttyrec library function 5 years ago
Matthew Faltys ee891cd615 Add parameters for save file caching 5 years ago
Matthew Faltys f79108ca31 Remove debug statement 5 years ago
Matthew Faltys 2439ca2771 Bump SOTW version 5 years ago
Matthew Faltys 66b958d952 Add janitor job to clean up old files 5 years ago
Matthew Faltys 55bc624128 Add ability to edit sotw config 5 years ago
Matthew Faltys 4fb58d628a Update stock ini to match seasons 5 years ago
Matthew Faltys cdafa1b2f3 Check user files on login (migration) 5 years ago
Matthew Faltys 47f4886b48 Update seed score file 5 years ago
Matthew Faltys 7a3357f7c5 Merge branch 'feature/sotw' of https://git.unixvoid.com/mfaltys/nethack-launcher into feature/sotw 5 years ago
Matthew Faltys f6cd22a3b9 Add score persistence 5 years ago
Matthew Faltys 2dac08c098 Bump sotw version 5 years ago
Matthew Faltys d5f4aa988d Add sotw 1.1.6 5 years ago
Matthew Faltys a6a0e72a00 Add stable redis version to docker 5 years ago
Matthew Faltys 39714170a1 Add Shadow of the Wyrm to launcher 5 years ago
  1. 14
      Makefile
  2. 4
      config.gcfg
  3. 27
      deps/Dockerfile
  4. 5
      deps/chowner.sh
  5. 30
      deps/clean.sh
  6. 25
      deps/link_sotw.sh
  7. BIN
      deps/scores.dat
  8. 19
      nethack-launcher/cleanup.go
  9. 5
      nethack-launcher/create_initial_files.go
  10. 5
      nethack-launcher/create_user_files.go
  11. 144
      nethack-launcher/library.go
  12. 4
      nethack-launcher/nethack-launcher.go
  13. 1
      nethack-launcher/print_login_screen.go
  14. 57
      nethack-launcher/print_user_screen.go
  15. 9
      nethack-launcher/print_welcome_screen.go
  16. 21
      nethack-launcher/run_game.go

14
Makefile

@ -11,9 +11,11 @@ all: stat
run:
go run \
nethack-launcher/check_dir.go \
nethack-launcher/cleanup.go \
nethack-launcher/create_initial_files.go \
nethack-launcher/create_user_files.go \
nethack-launcher/janitor.go \
nethack-launcher/library.go \
nethack-launcher/nethack-launcher.go \
nethack-launcher/print_change_password_screen.go \
nethack-launcher/print_high_scores.go \
@ -35,7 +37,7 @@ stat:
dependencies:
go get github.com/gorilla/mux
build_docker:
build_docker: fetch_sotw
mkdir -p stage.tmp/
cp deps/Dockerfile stage.tmp/
cp config.gcfg stage.tmp/config.gcfg
@ -46,9 +48,19 @@ build_docker:
cp deps/chowner.sh stage.tmp/
cp deps/run_nethack.sh stage.tmp/
cp deps/reclist.c stage.tmp/
cp deps/link_sotw.sh stage.tmp/
cp deps/clean.sh stage.tmp/
cp deps/scores.dat stage.tmp/
wget -O stage.tmp/redis-server https://cryo.unixvoid.com/bin/redis/5.0.7/redis-server
chmod +x stage.tmp/redis-server
cd stage.tmp/ && \
$(OS_PERMS) docker build -t $(IMAGE_NAME) .
fetch_sotw:
mkdir -p stage.tmp/
wget https://cryo.unixvoid.com/bin/misc/sotw/shadow-of-the-wyrm-release-1.2.2.tar.gz
mv shadow-of-the-wyrm-release-1.2.2.tar.gz stage.tmp/sotw.tar.gz
run_docker:
$(OS_PERMS) docker run \
-d \

4
config.gcfg

@ -6,6 +6,10 @@
nhdatlocation = "/NetHack/dat/nhdat"
recoverbinary = "/NetHack/util/recover"
sysconflocation = "/NetHack/sys/unix/sysconf"
ttyreccache = "10"
sotwversion = "1.2.2"
sotwroot = "/sotw"
sotwdumpcache = "5"
bootstrapdelay = 1
[redis]

27
deps/Dockerfile vendored

@ -1,13 +1,13 @@
FROM debian
FROM debian:stretch
# install needed packages
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
redis-server \
openssh-server \
autoconf \
bison \
bsdmainutils \
bzip2 \
flex \
gcc \
gdb \
@ -15,14 +15,26 @@ RUN apt-get update && \
groff \
libncursesw5-dev \
libsqlite3-dev \
libboost1.62-dev \
libboost-all-dev \
libncurses5-dev \
libncursesw5-dev \
lua5.1 \
liblua5.1-0-dev \
libsdl2-dev \
libsdl2-image-2.0-0 \
libsdl2-image-dev \
libxerces-c-dev \
make \
ncurses-dev \
premake4 \
sqlite3 \
tar \
telnetd \
xinetd \
locales \
git \
wget \
zlibc \
vim
RUN apt-get clean
@ -89,6 +101,7 @@ RUN gcc reclist.c -o /bin/reclist
RUN rm reclist.c
# copy in files
COPY redis-server /usr/bin/
COPY config.gcfg /
COPY nethack-launcher /
COPY redis.conf /
@ -96,5 +109,13 @@ COPY run.sh /
COPY chowner.sh /bin/
COPY nethackrc /.nethackrc
COPY run_nethack.sh /
COPY link_sotw.sh /bin/
COPY clean.sh /bin/
ADD sotw.tar.gz /
RUN mv /shadow-of-the-wyrm* /sotw/
COPY scores.dat /sotw/
# update ini to match current season by default
RUN cd /sotw && \
sed -i 's/current_month_is_start_month=0/current_month_is_start_month=1/g' swyrm.ini
CMD ["/run.sh"]

5
deps/chowner.sh vendored

@ -2,7 +2,12 @@
while :
do
# chown nethack directory
chown -R nethack:nethack /hack 2> /dev/null
chmod -R 744 /hack 2> /dev/null
# chown
chown -R nethack:nethack /sotw 2> /dev/null
chmod -R 744 /sotw 2> /dev/null
sleep 2
done

30
deps/clean.sh vendored

@ -0,0 +1,30 @@
#!/bin/bash
HACKDIR=$1
USERDIR=$2
TTYRECCACHE=$3
SOTWDUMPCACHE=$4
###
# clean old ttyrecs
###
cd /$HACKDIR/user/$USERDIR/ttyrec/
ls -1tr | head -n -$TTYRECCACHE | xargs -d '\n' rm -f --
###
# clean sotw files
###
cd /$HACKDIR/user/$USERDIR/sotw/
# there are always 4 symlinked files
# leave 5 of the latest dumps
DUMPFILES=$(expr $SOTWDUMPCACHE + 4)
FILES=$(ls -1tr *.txt | head -n -$DUMPFILES)
for f in $FILES; do
#test -h $f || echo "removing old file $f"
if [ ! -h $f ]; then
rm -rf $f
fi
done

25
deps/link_sotw.sh vendored

@ -0,0 +1,25 @@
#!/bin/bash
FILES=/sotw/*
USERDIR=$1
HACKDIR=$2
# create initial dir if it does not exist
mkdir -p $USERDIR/sotw/
# link all game files to user dir
for f in $FILES
do
echo "linking $f"
ln -s $f $USERDIR/sotw/
done
# remove inital score file
rm -rf $USERDIR/sotw/scores.dat
# link in shared score file from hackdir
ln -s $HACKDIR/scores.dat $USERDIR/sotw/
# remove initial config file
rm -rf $USERDIR/sotw/swyrm.ini
# copy in sotw config file
cp $HACKDIR/swyrm.ini $USERDIR/sotw/

BIN
deps/scores.dat vendored

Binary file not shown.

19
nethack-launcher/cleanup.go

@ -0,0 +1,19 @@
package main
import (
"fmt"
"os/exec"
)
func runCleanup(username string) {
// clean up ttyrecs in /<hackdir>/user/<username>/ttyrec/
// clean up sotw dumps, aka:
// non-symlinked .txt files in /<hackdir>/user/<username>/sotw/
// run cleanup file
out, err := exec.Command("/bin/clean.sh", config.NethackLauncher.HackDir, username, config.NethackLauncher.TTYRecCache, config.NethackLauncher.SotwDumpCache).Output()
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", out)
}

5
nethack-launcher/create_initial_files.go

@ -51,4 +51,9 @@ func createInitialFiles() {
}
}
// make sure initial sotw scores file exists
if _, err := os.Stat(fmt.Sprintf("%s/scores.dat", config.NethackLauncher.HackDir)); os.IsNotExist(err) {
exec.Command("cp", fmt.Sprintf("%s/scores.dat", config.NethackLauncher.SotwRoot), config.NethackLauncher.HackDir).Run()
}
}

5
nethack-launcher/create_user_files.go

@ -39,4 +39,9 @@ func createUserFiles(username string) {
// move in nhdat file if it does not exist
exec.Command("cp", fmt.Sprintf("%s/nhdat", config.NethackLauncher.HackDir), userpath).Run()
// run sotw prep script
if _, err := os.Stat(fmt.Sprintf("%s/sotw/", userpath)); os.IsNotExist(err) {
exec.Command("/bin/link_sotw.sh", userpath, config.NethackLauncher.HackDir).Run()
}
}

144
nethack-launcher/library.go

@ -0,0 +1,144 @@
package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strconv"
"strings"
"gopkg.in/redis.v5"
)
func printLibraryScreen(redisClient *redis.Client, username string) {
// print header
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
println(" Choose a users library to view ('enter' without selection returns)")
println("")
us, err := ioutil.ReadDir(fmt.Sprintf("/%s/user", config.NethackLauncher.HackDir))
if err != nil {
println(" No users exist ('enter' without selection returns)")
panic(err)
}
users := make(map[int]string)
usersTimer := 1
for _, u := range us {
fmt.Printf(" %d) %s\n", usersTimer, u.Name())
// add user to line map
users[usersTimer] = fmt.Sprintf("%s", u.Name())
usersTimer++
}
fmt.Println("")
fmt.Printf(">> ")
// start user input
// 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)
s, _ := strconv.Atoi(string(b))
// check if user is trying to navigate
if string(b) == "\n" {
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
clearScreen()
if username == "" {
clearScreen()
printWelcomeScreen(redisClient)
} else {
clearScreen()
printUserScreen(redisClient, username)
}
}
// check if selection is in out map
if users[s] != "" {
user := strings.Split(users[s], ":")
fmt.Printf("going to spectate '%s'\n", user[0])
clearScreen()
printUserLibraryScreen(redisClient, username, user[0])
}
}
}
func printUserLibraryScreen(redisClient *redis.Client, username, currentUser string) {
// print header
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
println(" Choose a ttyrec to view ('enter' without selection returns)")
println(" The following keybinds are available during playback:")
println(" • + or f: double the speed of playback")
println(" • - or s: halve the speed of playback")
println(" • 0: set playback speed to 0, pausing playback")
println(" • 1: set playback speed to 1 again")
println("")
t, err := ioutil.ReadDir(fmt.Sprintf("/%s/user/%s/ttyrec", config.NethackLauncher.HackDir, currentUser))
if err != nil {
println(" No ttyrecs exist ('enter' without selection returns)")
panic(err)
}
ttyrecs := make(map[int]string)
ttyrecsTimer := 1
for _, ty := range t {
fmt.Printf(" %d) %s\n", ttyrecsTimer, ty.Name())
// add user to line map
ttyrecs[ttyrecsTimer] = fmt.Sprintf("%s", ty.Name())
ttyrecsTimer++
}
fmt.Println("")
fmt.Printf(">> ")
// start user input
// disable input buffering
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
// enable showing input on screen
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if scanner.Text() == "" {
clearScreen()
printLibraryScreen(redisClient, username)
}
// save input
s := scanner.Text()
sel, err := strconv.Atoi(s)
if err != nil {
fmt.Printf(" There was a problem with your last entry.\n>> ")
}
// check if selection is in our map
if ttyrecs[sel] != "" {
fmt.Printf("going to watch '%s'\n", ttyrecs[sel])
clearScreen()
// set ttyrec path
ttyrecPath := fmt.Sprintf("%s/user/%s/ttyrec/%s", config.NethackLauncher.HackDir, username, ttyrecs[sel])
tp := exec.Command("ttyplay", ttyrecPath)
tp.Stdout = os.Stdout
tp.Stdin = os.Stdin
tp.Stderr = os.Stderr
err := tp.Run()
if err != nil {
fmt.Print(err)
}
}
clearScreen()
printUserLibraryScreen(redisClient, username, currentUser)
}
}

4
nethack-launcher/nethack-launcher.go

@ -20,6 +20,10 @@ type Config struct {
NhdatLocation string
RecoverBinary string
SysconfLocation string
TTYRecCache string
SotwVersion string
SotwRoot string
SotwDumpCache string
BootstrapDelay time.Duration
}

1
nethack-launcher/print_login_screen.go

@ -52,6 +52,7 @@ func printLoginScreen(redisClient *redis.Client) {
typedHash := sha3.Sum512([]byte(typedAuth))
if fmt.Sprintf("%x", typedHash) == storedHash {
// user authed
createUserFiles(username)
printUserScreen(redisClient, username)
noPass = false
} else {

57
nethack-launcher/print_user_screen.go

@ -12,17 +12,25 @@ import (
func printUserScreen(redisClient *redis.Client, username string) string {
clearScreen()
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
fmt.Printf(" Logged in as: %s\n", username)
println("")
println("Global")
println(" l) Logout")
println(" c) Change password")
println(" w) Watch games in progress")
println(" h) View highscores")
println(" a) View all scores")
println(" e) Edit config")
println(" r) Recover from crash")
println(" x) Browse library of ttyrecs")
println("")
println("Shadow of the Wyrm")
println(" f) Edit SOTW config")
fmt.Printf(" o) Play Shadow of the Wyrm %s\n", config.NethackLauncher.SotwVersion)
println("")
println("Nethack")
println(" h) View NetHack highscores")
println(" a) View all NetHack scores")
println(" e) Edit NetHack config")
println(" r) Recover NetHack from crash")
fmt.Printf(" p) Play NetHack %s\n", config.NethackLauncher.NethackVersion)
println("")
println(" q) Quit")
println("")
fmt.Printf(">> ")
@ -45,7 +53,30 @@ func printUserScreen(redisClient *redis.Client, username string) string {
hackRCLoc := fmt.Sprintf("%s/user/%s/.nethackrc", config.NethackLauncher.HackDir, username)
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
clearScreen()
nh := exec.Command("vim", "-Z", hackRCLoc)
nh := exec.Command("vim", "-i", "NONE", "-Z", hackRCLoc)
nh.Stdout = os.Stdout
nh.Stdin = os.Stdin
nh.Stderr = os.Stderr
nh.Run()
clearScreen()
printUserScreen(redisClient, username)
case "f":
// check if the file has been uplifted
SOTWLoc := fmt.Sprintf("%s/user/%s/sotw/swyrm.ini", config.NethackLauncher.HackDir, username)
il, _ := os.Lstat(SOTWLoc)
if il.Mode()&os.ModeSymlink == os.ModeSymlink {
// the file is still a legacy symlink, remove and recopy
err := os.Remove(SOTWLoc)
if err != nil {
fmt.Println(err)
}
SOTWOrigin := fmt.Sprintf("%s/swyrm.ini", config.NethackLauncher.SotwRoot)
exec.Command("cp", SOTWOrigin, SOTWLoc).Run()
}
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
clearScreen()
nh := exec.Command("vim", "-i", "NONE", "-Z", SOTWLoc)
nh.Stdout = os.Stdout
nh.Stdin = os.Stdin
nh.Stderr = os.Stderr
@ -58,6 +89,9 @@ func printUserScreen(redisClient *redis.Client, username string) string {
case "w":
clearScreen()
printProgressScreen(redisClient, username)
case "x":
clearScreen()
printLibraryScreen(redisClient, username)
case "h":
clearScreen()
printHighScores(redisClient, username)
@ -69,6 +103,17 @@ func printUserScreen(redisClient *redis.Client, username string) string {
currentTime := time.Now().UTC()
fulltime := currentTime.Format("2006-01-02.03:04:05")
go runGame(username, fulltime)
go runCleanup(username)
watcher := startWatcher(username, fulltime, redisClient)
wg.Wait()
close(watcher)
printUserScreen(redisClient, username)
case "o":
wg.Add(1)
currentTime := time.Now().UTC()
fulltime := currentTime.Format("2006-01-02.03:04:05")
go runSotwGame(username, fulltime)
go runCleanup(username)
watcher := startWatcher(username, fulltime, redisClient)
wg.Wait()
close(watcher)

9
nethack-launcher/print_welcome_screen.go

@ -11,14 +11,11 @@ import (
func printWelcomeScreen(redisClient *redis.Client) string {
clearScreen()
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
println(" Not logged in.")
println("")
println(" l) Login")
println(" r) Register new user")
println(" w) Watch games in progress")
println(" h) View highscores")
println(" a) View all scores")
println(" q) Quit")
println("")
fmt.Printf(">> ")
@ -45,12 +42,6 @@ func printWelcomeScreen(redisClient *redis.Client) string {
case "w":
clearScreen()
printProgressScreen(redisClient, "")
case "h":
clearScreen()
printHighScores(redisClient, "")
case "a":
clearScreen()
printAllScores(redisClient, "")
case "q":
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
clearScreen()

21
nethack-launcher/run_game.go

@ -40,6 +40,27 @@ func runGame(username, timestamp string) {
wg.Done()
}
func runSotwGame(username, timestamp string) {
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, "--", "./ShadowOfTheWyrm")
nh.Dir = (fmt.Sprintf("%s/user/%s/sotw/", 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("")

Loading…
Cancel
Save