~whereswaldon/pointstar

ref: v0.0.1 pointstar/client/main.go -rw-r--r-- 2.8 KiB
1e806177Chris Waldon bugfix: avoid crashing when laying out help 1 year, 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main

import (
	"context"
	"flag"

	"gioui.org/app"
	"gioui.org/font/gofont"
	"gioui.org/io/system"
	"gioui.org/layout"
	"nhooyr.io/websocket"

	"git.sr.ht/~whereswaldon/pointstar/client/log"
	"git.sr.ht/~whereswaldon/pointstar/client/widgets/gameui"
	"git.sr.ht/~whereswaldon/pointstar/gamestate"
	"git.sr.ht/~whereswaldon/pointstar/server/protocol"
)

func main() {
	flag.Parse()
	protocol.Register()
	go func() {
		w := app.NewWindow()
		if err := eventLoop(w); err != nil {
			log.Println(err)
			return
		}
	}()
	app.Main()
}

type WSWorker struct {
	Address    string
	FromServer chan interface{}
	ToServer   chan interface{}
}

func (w *WSWorker) Run(window *app.Window) {
	ctx := context.Background()
	socket, _, err := websocket.Dial(ctx, w.Address, nil)
	if err != nil {
		log.Printf("websocket error: %v", err)
	}
	p := &protocol.PlayerConn{Conn: socket, Context: ctx}
	w.FromServer <- nil // send something to indicate that we're connected
	window.Invalidate()
	go func() {
		defer close(w.FromServer)
		for {
			if msgs, err := p.Recv(); err != nil {
				log.Printf("failed receiving from server: %v", err)
				window.Invalidate()
				return
			} else {
				for _, msg := range msgs {
					log.Printf("relaying message %v to front end", msg)
					w.FromServer <- msg
					window.Invalidate()
				}
			}
		}
	}()
	for msg := range w.ToServer {
		if err := p.Send(msg); err != nil {
			log.Printf("Failed sending set name: %v", err)
		}
	}
}

func eventLoop(w *app.Window) error {
	game := &gamestate.GameState{}
	ui := UIState{
		PlayerNum: -1, // indicate that it isn't set yet
	}
	ui.NameEditor.SingleLine = true
	fromServer := make(chan interface{}, 1)
	toServer := make(chan interface{}, 1)
	address := GetWSURL()
	if address == "" {
		address = "ws://localhost:8080/ws"
	}
	ui.Worker = &WSWorker{
		Address:    address,
		FromServer: fromServer,
		ToServer:   toServer,
	}
	go ui.Worker.Run(w)

	gofont.Register()
	th := gameui.NewGameTheme()
	skin := &Skin{th}
	gtx := new(layout.Context)
	for {
		switch e := (<-w.Events()).(type) {
		case system.DestroyEvent:
			return e.Err
		case system.FrameEvent:
			select {
			case msg, stillOpen := <-fromServer:
				ui.HasConnected = true
				ui.Connected = stillOpen
				log.Printf("front end read %v from server", msg)
				// receive a new game state if one is available
				switch message := msg.(type) {
				case protocol.AssignPlayerNumber:
					log.Println("assigned player number")
					ui.PlayerNum = message.Number
				case *gamestate.GameState:
					log.Println("game state updated")
					game = message
					ui.Update(game)
				case protocol.ErrorMessage:
					log.Printf("server sent error: %s", message.Message)
				default:
					log.Printf("Unknown message from server (type %T): %v", message, message)
				}
			default:
			}
			gtx.Reset(e.Queue, e.Config, e.Size)
			skin.LayoutAll(game, &ui, gtx)
			e.Frame(gtx.Ops)
		}
	}
}