Browse Source

added dialogues

added server
added server connection to client
main
Pixdigit 12 months ago
parent
commit
e7c1b072e7
  1. 72
      client/backlog.go
  2. 91
      client/dialogue.go
  3. 23
      client/displayManager.go
  4. 16
      client/init.go
  5. 51
      client/main.go
  6. 42
      client/networking.go
  7. 48
      client/state.go
  8. 1
      go.mod
  9. 2
      go.sum
  10. 50
      server/main.go

72
client/backlog.go

@ -0,0 +1,72 @@
package main
import (
"strings"
)
type backlog struct {
lines [][]rune
}
var chat = backlog{lines: [][]rune{[]rune(""), []rune(""), []rune(""), []rune(""), []rune(""), []rune("")}}
func toRunes(lines []string) [][]rune {
chars := make([][]rune, len(lines))
for i, line := range lines {
chars[i] = []rune(line)
}
return chars
}
func toStrings(chars [][]rune) []string {
lines := make([]string, len(chars))
for i, line := range chars {
lines[i] = string(line)
}
return lines
}
func (b *backlog) last(n int) []string {
end := len(b.lines)
return toStrings(b.lines[end-n : end])
}
func (b *backlog) addln(str ...string) {
str = append(str, "")
b.lines = append(b.lines, toRunes(str)...)
}
func (b *backlog) pushChar(char rune) {
end := len(b.lines) - 1
if len(b.lines[end]) >= 38 {
return
}
b.lines[end] = append(b.lines[end], char)
}
func (b *backlog) popChar() rune {
end := len(b.lines) - 1
if len(b.lines[end]) == 0 {
return ' '
}
char := b.lines[end][len(b.lines[end])-1]
b.lines[end] = b.lines[end][0 : len(b.lines[end])-1]
return char
}
func (b *backlog) show() {
size := 5
_, screenHeight := screen.Size()
opts := boxOpts{
offset: vec2{
0,
screenHeight - size - 2,
},
minSize: vec2{
40,
5,
},
}
box(strings.Join(b.last(size), "\n")+"_", opts)
}

91
client/dialogue.go

@ -0,0 +1,91 @@
package main
import (
"fmt"
"strings"
"github.com/gdamore/tcell"
)
type vec2 struct {
x, y int
}
type boxOpts struct {
offset vec2
minSize vec2
fillX bool
fillY bool
}
func box(text string, opts boxOpts) {
lines := strings.Split(text, "\n")
maxLen := 0
for _, line := range lines {
if len(line) > maxLen {
maxLen = len(line)
}
}
size := vec2{
x: maxLen,
y: len(lines) + 1,
}
chars := make([][]rune, len(lines))
// Fix string indexing
for i, line := range lines {
chars[i] = []rune(line)
}
if opts.minSize.x > size.x {
size.x = opts.minSize.x
}
if opts.minSize.y > size.y {
size.y = opts.minSize.y
}
if opts.fillX {
size.x, _ = screen.Size()
size.x -= 1
}
if opts.fillY {
_, size.y = screen.Size()
size.y -= 1
}
borderStyle := tcell.StyleDefault
for x := 0; x <= size.x; x += 1 {
for y := 0; y <= size.y; y += 1 {
var char rune
switch {
case x == 0 && y == 0:
char = '┌'
case x == size.x && y == 0:
char = '┐'
case x == 0 && y == size.y:
char = '└'
case x == size.x && y == size.y:
char = '┘'
case x == 0 || x == size.x:
char = '│'
case y == 0 || y == size.y:
char = '─'
case 0 < y && y <= len(chars) && 0 < x && x <= len(chars[y-1]):
char = rune(chars[y-1][x-1])
}
screen.SetContent(x+opts.offset.x, y+opts.offset.y, char, nil, borderStyle)
}
}
}
func choiceBox(question string, answers []string, opts boxOpts) {
text := question + "\n"
for i, answer := range answers {
text += fmt.Sprintf("%v) %v\n", i+1, answer)
}
box(text, opts)
}

23
client/displayManager.go

@ -1,9 +1,31 @@
package main
import (
"fmt"
"time"
"github.com/gdamore/tcell"
)
func initScreen() {
var err error
// initialize tcell
if screen, err = tcell.NewScreen(); err != nil {
panic(fmt.Sprintf("Could create Screen:%v\n", err))
}
err = screen.Init()
if err != nil {
panic(fmt.Sprintf("Could not init screen:%v\n", err))
}
screen.HideCursor()
screen.SetStyle(tcell.StyleDefault.
Background(tcell.ColorBlack).
Foreground(tcell.ColorWhite))
screen.Clear()
}
func refresh(fps uint) {
exitChan := shutdownBroadcast.Subscribe()
go func() {
@ -12,6 +34,7 @@ func refresh(fps uint) {
for !done {
select {
case <-fpsTicker.C:
chat.show()
screen.Show()
case <-exitChan:
done = true

16
client/init.go

@ -0,0 +1,16 @@
package main
import (
"os"
"os/signal"
)
func listenShutdown() {
go func() {
sigChan := make(chan os.Signal)
signal.Notify(sigChan, os.Interrupt)
signal.Notify(sigChan, os.Kill)
<-sigChan
shutdownBroadcast.Send(nil)
}()
}

51
client/main.go

@ -4,8 +4,6 @@ import (
"fmt"
//"math/rand"
//"time"
"os"
"os/signal"
"git.pixdigit.tk/Pixdigit/broadcast"
"github.com/davecgh/go-spew/spew"
@ -18,49 +16,20 @@ type options struct {
var shutdownBroadcast = broadcast.Broadcast{}
var screen tcell.Screen
var state = stateInit
var opts = options{
FPS: 60,
}
func initTCell() {
var err error
// initialize tcell
if screen, err = tcell.NewScreen(); err != nil {
panic(fmt.Sprintf("Could create Screen:%v\n", err))
}
err = screen.Init()
if err != nil {
panic(fmt.Sprintf("Could not init screen:%v\n", err))
}
}
func initScreen() {
screen.HideCursor()
screen.SetStyle(tcell.StyleDefault.
Background(tcell.ColorBlack).
Foreground(tcell.ColorWhite))
screen.Clear()
}
func listenShutdown() {
go func() {
sigChan := make(chan os.Signal)
signal.Notify(sigChan, os.Interrupt)
signal.Notify(sigChan, os.Kill)
<-sigChan
shutdownBroadcast.Send(nil)
}()
}
func setup() {
//rand.Seed(time.Now().UnixNano())
initLogger()
initTCell()
initScreen()
refresh(opts.FPS)
initNetworking()
listenShutdown()
setState(stateStart)
}
func main() {
@ -70,19 +39,21 @@ func main() {
for !done {
event := screen.PollEvent()
if event != nil {
log("Got event: %v", spew.Sdump(event))
// switch on event type
switch ev := event.(type) {
case *tcell.EventKey:
switch ev.Key() {
case tcell.KeyCtrlZ, tcell.KeyCtrlC:
done = true
case tcell.KeyEnter:
done = processInput(chat.last(1)[0])
case tcell.KeyBackspace:
case tcell.KeyBackspace2:
chat.popChar()
case tcell.KeyRune:
switch ev.Rune() {
case 'q':
done = true
}
chat.pushChar(ev.Rune())
default:
log("Unprocessed event: %v", spew.Sdump(event))
}
case *tcell.EventResize:

42
client/networking.go

@ -0,0 +1,42 @@
package main
import (
"net/url"
"time"
"github.com/gorilla/websocket"
)
var serverAddr = url.URL{
Scheme: "ws",
Host: "localhost:8080",
Path: "/",
}
/*
Scheme: "ws",
Host: "gmtk.pixdigit.tk",
Path: "/",
*/
func initNetworking() {
c, r, err := websocket.DefaultDialer.Dial(serverAddr.String(), nil)
if err != nil {
panic("Sorry, networking is unavailable or the server is unreachable: " + err.Error())
}
go func() {
shutdownBroadcast.WaitNext()
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseGoingAway, ""))
if err != nil {
log("Websocket close error:", err)
return
}
<-time.After(time.Second)
return
}()
log("Got connection")
_, _ = c, r
}

48
client/state.go

@ -0,0 +1,48 @@
package main
type gameState uint
const (
stateInit = gameState(iota)
stateStart
stateJoin
stateCreate
stateIngame
stateAfterGame
)
var isHost bool
func setState(state gameState) {
screen.Clear()
switch state {
case stateStart:
choiceBox("Hello.\nWould you like to:", []string{"Create a lobby", "Join a lobby"}, boxOpts{fillX: true})
}
}
func processInput(in string) bool {
if in == "quit" || in == "exit" {
return true
}
switch state {
case stateStart:
switch in {
case "1":
chat.addln("Creating Lobby")
//TODO
case "2":
chat.addln("Creating Lobby")
//TODO
default:
chat.addln("That is not a valid answer, try again.")
}
default:
chat.addln("Oh no, I was not expecting that answer.", "Could you try a different one?")
}
return false
}

1
go.mod

@ -6,4 +6,5 @@ require (
git.pixdigit.tk/Pixdigit/broadcast v0.0.1
github.com/davecgh/go-spew v1.1.1
github.com/gdamore/tcell v1.4.0
github.com/gorilla/websocket v1.4.2
)

2
go.sum

@ -6,6 +6,8 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=

50
server/main.go

@ -0,0 +1,50 @@
package main
import (
"fmt"
"net/http"
"github.com/gorilla/websocket"
)
type session struct {
sessionKey string
}
type userID int
var sessions = make([]session, 0)
var players = make(map[userID]session)
var upgrader = websocket.Upgrader{}
func wsHandler(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("Rejected connection: " + err.Error())
return
}
fmt.Println("Got new connection")
for {
mt, message, err := c.ReadMessage()
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
fmt.Println("Connection read error: " + err.Error())
break
}
fmt.Printf("recv: %s", message)
err = c.WriteMessage(mt, message)
if err != nil {
fmt.Println("write:", err)
break
}
}
}
func main() {
http.HandleFunc("/", wsHandler)
err := http.ListenAndServe("localhost:8080", nil)
if err != nil {
panic("Unable to start server: " + err.Error())
}
}
Loading…
Cancel
Save