Update develop with new SOTW build #1

Merged
mfaltys merged 16 commits from feature/sotw into develop 2 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: run:
go run \ go run \
nethack-launcher/check_dir.go \ nethack-launcher/check_dir.go \
nethack-launcher/cleanup.go \
nethack-launcher/create_initial_files.go \ nethack-launcher/create_initial_files.go \
nethack-launcher/create_user_files.go \ nethack-launcher/create_user_files.go \
nethack-launcher/janitor.go \ nethack-launcher/janitor.go \
nethack-launcher/library.go \
nethack-launcher/nethack-launcher.go \ nethack-launcher/nethack-launcher.go \
nethack-launcher/print_change_password_screen.go \ nethack-launcher/print_change_password_screen.go \
nethack-launcher/print_high_scores.go \ nethack-launcher/print_high_scores.go \
@ -35,7 +37,7 @@ stat:
dependencies: dependencies:
go get github.com/gorilla/mux go get github.com/gorilla/mux
build_docker: build_docker: fetch_sotw
mkdir -p stage.tmp/ mkdir -p stage.tmp/
cp deps/Dockerfile stage.tmp/ cp deps/Dockerfile stage.tmp/
cp config.gcfg stage.tmp/config.gcfg cp config.gcfg stage.tmp/config.gcfg
@ -46,9 +48,19 @@ build_docker:
cp deps/chowner.sh stage.tmp/ cp deps/chowner.sh stage.tmp/
cp deps/run_nethack.sh stage.tmp/ cp deps/run_nethack.sh stage.tmp/
cp deps/reclist.c 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/ && \ cd stage.tmp/ && \
$(OS_PERMS) docker build -t $(IMAGE_NAME) . $(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: run_docker:
$(OS_PERMS) docker run \ $(OS_PERMS) docker run \
-d \ -d \

4
config.gcfg

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

27
deps/Dockerfile vendored

@ -1,13 +1,13 @@
FROM debian FROM debian:stretch
# install needed packages # install needed packages
RUN apt-get update && \ RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \ DEBIAN_FRONTEND=noninteractive apt-get install -y \
redis-server \
openssh-server \ openssh-server \
autoconf \ autoconf \
bison \ bison \
bsdmainutils \ bsdmainutils \
bzip2 \
flex \ flex \
gcc \ gcc \
gdb \ gdb \
@ -15,14 +15,26 @@ RUN apt-get update && \
groff \ groff \
libncursesw5-dev \ libncursesw5-dev \
libsqlite3-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 \ make \
ncurses-dev \ ncurses-dev \
premake4 \
sqlite3 \ sqlite3 \
tar \ tar \
telnetd \ telnetd \
xinetd \ xinetd \
locales \ locales \
git \ wget \
zlibc \
vim vim
RUN apt-get clean RUN apt-get clean
@ -89,6 +101,7 @@ RUN gcc reclist.c -o /bin/reclist
RUN rm reclist.c RUN rm reclist.c
# copy in files # copy in files
COPY redis-server /usr/bin/
COPY config.gcfg / COPY config.gcfg /
COPY nethack-launcher / COPY nethack-launcher /
COPY redis.conf / COPY redis.conf /
@ -96,5 +109,13 @@ COPY run.sh /
COPY chowner.sh /bin/ COPY chowner.sh /bin/
COPY nethackrc /.nethackrc COPY nethackrc /.nethackrc
COPY run_nethack.sh / 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"] CMD ["/run.sh"]

5
deps/chowner.sh vendored

@ -2,7 +2,12 @@
while : while :
do do
# chown nethack directory
chown -R nethack:nethack /hack 2> /dev/null chown -R nethack:nethack /hack 2> /dev/null
chmod -R 744 /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 sleep 2
done 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 // move in nhdat file if it does not exist
exec.Command("cp", fmt.Sprintf("%s/nhdat", config.NethackLauncher.HackDir), userpath).Run() 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 NhdatLocation string
RecoverBinary string RecoverBinary string
SysconfLocation string SysconfLocation string
TTYRecCache string
SotwVersion string
SotwRoot string
SotwDumpCache string
BootstrapDelay time.Duration BootstrapDelay time.Duration
} }

1
nethack-launcher/print_login_screen.go

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

57
nethack-launcher/print_user_screen.go

@ -12,17 +12,25 @@ import (
func printUserScreen(redisClient *redis.Client, username string) string { func printUserScreen(redisClient *redis.Client, username string) string {
clearScreen() clearScreen()
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay) fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("")
fmt.Printf(" Logged in as: %s\n", username) fmt.Printf(" Logged in as: %s\n", username)
println("") println("")
println("Global")
println(" l) Logout") println(" l) Logout")
println(" c) Change password") println(" c) Change password")
println(" w) Watch games in progress") println(" w) Watch games in progress")
println(" h) View highscores") println(" x) Browse library of ttyrecs")
println(" a) View all scores") println("")
println(" e) Edit config") println("Shadow of the Wyrm")
println(" r) Recover from crash") 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) fmt.Printf(" p) Play NetHack %s\n", config.NethackLauncher.NethackVersion)
println("")
println(" q) Quit") println(" q) Quit")
println("") println("")
fmt.Printf(">> ") 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) hackRCLoc := fmt.Sprintf("%s/user/%s/.nethackrc", config.NethackLauncher.HackDir, username)
exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run() exec.Command("stty", "-F", "/dev/tty", "echo", "-cbreak").Run()
clearScreen() 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.Stdout = os.Stdout
nh.Stdin = os.Stdin nh.Stdin = os.Stdin
nh.Stderr = os.Stderr nh.Stderr = os.Stderr
@ -58,6 +89,9 @@ func printUserScreen(redisClient *redis.Client, username string) string {
case "w": case "w":
clearScreen() clearScreen()
printProgressScreen(redisClient, username) printProgressScreen(redisClient, username)
case "x":
clearScreen()
printLibraryScreen(redisClient, username)
case "h": case "h":
clearScreen() clearScreen()
printHighScores(redisClient, username) printHighScores(redisClient, username)
@ -69,6 +103,17 @@ func printUserScreen(redisClient *redis.Client, username string) string {
currentTime := time.Now().UTC() currentTime := time.Now().UTC()
fulltime := currentTime.Format("2006-01-02.03:04:05") fulltime := currentTime.Format("2006-01-02.03:04:05")
go runGame(username, fulltime) 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) watcher := startWatcher(username, fulltime, redisClient)
wg.Wait() wg.Wait()
close(watcher) close(watcher)

9
nethack-launcher/print_welcome_screen.go

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

21
nethack-launcher/run_game.go

@ -40,6 +40,27 @@ func runGame(username, timestamp string) {
wg.Done() 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) { func runtimeRecover(username string) {
fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay) fmt.Printf(" %s\n", config.NethackLauncher.ServerDisplay)
println("") println("")

Loading…
Cancel
Save