gosl/cmd/server.go

142 lines
3.3 KiB
Go
Raw Normal View History

2016-01-18 23:19:51 +01:00
package cmd // code.bitsetter.de/fun/gosl/cmd
import (
2016-02-05 16:19:43 +01:00
"encoding/gob"
2016-01-19 16:51:50 +01:00
"log"
"net"
"sort"
"time"
2016-01-18 23:19:51 +01:00
"github.com/spf13/cobra"
"code.bitsetter.de/fun/gosl/data"
2016-01-18 23:19:51 +01:00
)
var cmdServer = &cobra.Command{
Use: "server",
Short: "Runs Gosl as a server",
2016-02-05 16:19:43 +01:00
Long: `Runs Gosl as a server
[TODO:]
gosl.json for configuration (Port/Address, Level)
2016-02-05 16:19:43 +01:00
`,
2016-01-18 23:19:51 +01:00
// Run:
}
2016-02-08 19:54:28 +01:00
const ClientOffset = 0
2016-02-08 15:29:43 +01:00
type goslClient struct {
con *net.TCPConn
id int
w int
h int
off int
}
/* GLOBAL SERVER STATE */
2016-02-06 01:48:29 +01:00
var (
LevelFile string
level *data.Level
2016-02-06 01:48:29 +01:00
ServerPort int
2016-02-08 15:29:43 +01:00
TotalWidth int = 0
clients map[int]*goslClient = make(map[int]*goslClient)
clientKeys []int = make([]int, 0)
// big server canvas
2016-02-08 15:29:43 +01:00
//canvas [][]rune
canvasX int
frameCounter int = 0
2016-02-06 01:48:29 +01:00
)
2016-01-19 16:51:50 +01:00
func handleConn(conn *net.TCPConn) {
2016-02-06 15:18:07 +01:00
var hs data.Handshake
2016-01-19 16:51:50 +01:00
log.Println("Got a connection!")
2016-02-06 21:47:06 +01:00
dec := gob.NewDecoder(conn)
dec.Decode(&hs) // decode handshake
log.Println("Got client! ID:", hs.ID, "dimensions:", hs.W, hs.H)
// memorize client in server state
clientKeys = append(clientKeys, hs.ID)
sort.Ints(clientKeys)
2016-02-08 15:29:43 +01:00
clients[hs.ID] = &goslClient{con: conn, id: hs.ID, w: hs.W, h: hs.H}
TotalWidth += hs.W
// reset server
resetServer()
}
func resetServer() {
// adjust canvas width
2016-02-08 15:29:43 +01:00
canvasX = -1 * ClientOffset
for _, k := range clientKeys {
_, client := k, clients[k]
2016-02-08 15:29:43 +01:00
canvasX += client.w + ClientOffset
}
2016-02-08 19:13:05 +01:00
//canvasX += level.Width()
// adjust client offsets
off := 0
for _, k := range clientKeys {
2016-02-08 15:29:43 +01:00
clients[k].off = off
off += clients[k].w
off += ClientOffset
}
}
func serveClients() {
level = data.LoadLevel(LevelFile)
frameCounter = 0
for { // while true
2016-02-07 17:46:20 +01:00
if len(clients) > 0 { // pause if no clients are connected
for _, k := range clientKeys {
id, client := k, clients[k]
if id > 0 {
2016-02-08 15:29:43 +01:00
oFrame := level.GetFrame(client.off, client.w, canvasX, frameCounter)
2016-02-07 17:46:20 +01:00
enc := gob.NewEncoder(client.con)
err := enc.Encode(oFrame)
if err != nil {
// client disconnected
//log.Println("BEFORE remove: clients:", clients, " clientKeys:", clientKeys)
// delete client
delete(clients, client.id)
// delete client key
// ugly as fuck in go to remove from a slice
// it *should* work though
idInKeys := sort.SearchInts(clientKeys, client.id)
clientKeys = append(clientKeys[:idInKeys], clientKeys[idInKeys+1:]...)
//log.Println("AFTER remove: clients:", clients, " clientKeys:", clientKeys)
2016-02-08 15:29:43 +01:00
resetServer()
2016-02-07 17:46:20 +01:00
}
//log.Println("ID:", id, "Client:", client)
2016-02-08 15:29:43 +01:00
2016-02-06 21:47:06 +01:00
}
}
2016-02-07 17:46:20 +01:00
frameCounter++
time.Sleep(time.Second / time.Duration(level.FPS))
}
}
2016-01-19 16:51:50 +01:00
}
2016-01-18 23:19:51 +01:00
func runServer(cmd *cobra.Command, args []string) {
log.Println("Running server on port", ServerPort)
2016-02-06 01:48:29 +01:00
listener, err := net.ListenTCP("tcp", &net.TCPAddr{Port: ServerPort})
2016-01-19 16:51:50 +01:00
if err != nil {
log.Fatal(err)
panic("Could not open Listener")
}
defer listener.Close()
go serveClients()
2016-01-19 16:51:50 +01:00
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Fatal(err)
panic("Listener could not accept connection!")
}
go handleConn(conn)
}
2016-01-18 23:19:51 +01:00
}
func init() {
2016-02-06 01:48:29 +01:00
CmdGosl.AddCommand(cmdServer)
2016-01-18 23:19:51 +01:00
cmdServer.Run = runServer
2016-02-06 01:48:29 +01:00
2016-02-06 13:26:01 +01:00
cmdServer.Flags().StringVarP(&LevelFile, "level", "l", "default.lvl", "Use specific levelfile")
2016-02-06 01:48:29 +01:00
cmdServer.Flags().IntVarP(&ServerPort, "port", "p", 8090, "Run server on this port")
2016-01-18 23:19:51 +01:00
}