cloud-game/main.go
2019-04-06 05:21:16 +08:00

188 lines
4 KiB
Go

package main
import (
pionRTC "github.com/pions/webrtc"
"fmt"
"image"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/giongto35/game-online/ui"
"github.com/giongto35/game-online/util"
"github.com/giongto35/game-online/webrtc"
// "github.com/gorilla/mux"
"github.com/gorilla/websocket"
"encoding/json"
)
// var webRTC *webrtc.WebRTC
var width = 256
var height = 240
// var gameName = "supermariobros.rom"
var gameName string
// var FPS = 60
var upgrader = websocket.Upgrader{}
type WSPacket struct {
ID string `json:"id"`
Data string `json:"data"`
}
func init() {
}
func startGame(path string, imageChannel chan *image.RGBA, inputChannel chan int, webRTC *webrtc.WebRTC) {
ui.Run([]string{path}, imageChannel, inputChannel, webRTC)
}
func main() {
fmt.Println("http://localhost:8000")
fmt.Println(time.Now().UnixNano())
// router := mux.NewRouter()
// router.HandleFunc("/", getWeb).Methods("GET")
// router.HandleFunc("/session", postSession).Methods("POST")
// http.ListenAndServe(":8000", router)
// ignore origin
upgrader.CheckOrigin = func(r *http.Request) bool { return true }
http.HandleFunc("/", getWeb)
http.HandleFunc("/ws", ws)
http.ListenAndServe(":8000", nil)
}
func getWeb(w http.ResponseWriter, r *http.Request) {
bs, err := ioutil.ReadFile("./index.html")
if err != nil {
log.Fatal(err)
}
w.Write(bs)
}
func ws(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
defer c.Close()
log.Println("New Connection")
webRTC := webrtc.NewWebRTC()
// streaming game
// start new games and webrtc stuff?
isDone := false
for !isDone {
mt, message, err := c.ReadMessage()
if err != nil {
log.Println("[!] read:", err)
break
}
req := WSPacket{}
err = json.Unmarshal(message, &req)
if err != nil {
log.Println("[!] json unmarshal:", err)
break
}
// log.Println(req)
// connectivity
res := WSPacket{}
switch req.ID {
case "ping":
gameName = req.Data
log.Println("Ping from server with game:", gameName)
res.ID = "pong"
case "sdp":
log.Println("Received user SDP")
localSession, err := webRTC.StartClient(req.Data, width, height)
if err != nil {
log.Fatalln(err)
}
res.ID = "sdp"
res.Data = localSession
case "candidate":
hi := pionRTC.ICECandidateInit{}
err = json.Unmarshal([]byte(req.Data), &hi)
if err != nil {
log.Println("[!] Cannot parse candidate: ", err)
} else {
// webRTC.AddCandidate(hi)
}
res.ID = "candidate"
case "start":
log.Println("Starting game")
imageChannel := make(chan *image.RGBA, 100)
go screenshotLoop(imageChannel, webRTC)
go startGame("games/" + gameName, imageChannel, webRTC.InputChannel, webRTC)
res.ID = "start"
isDone = true
}
stRes, err := json.Marshal(res)
if err != nil {
log.Println("json marshal:", err)
}
err = c.WriteMessage(mt, []byte(stRes))
if err != nil {
log.Println("write:", err)
break
}
}
}
func postSession(w http.ResponseWriter, r *http.Request) {
bs, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
r.Body.Close()
webRTC := webrtc.NewWebRTC()
localSession, err := webRTC.StartClient(string(bs), width, height)
if err != nil {
log.Fatalln(err)
}
imageChannel := make(chan *image.RGBA, 100)
go screenshotLoop(imageChannel, webRTC)
go startGame("games/"+gameName, imageChannel, webRTC.InputChannel, webRTC)
w.Write([]byte(localSession))
}
// func screenshotLoop(imageChannel chan *image.RGBA) {
func screenshotLoop(imageChannel chan *image.RGBA, webRTC *webrtc.WebRTC) {
for image := range imageChannel {
// Client stopped
if webRTC.IsClosed() {
break
}
// encode frame
if webRTC.IsConnected() {
yuv := util.RgbaToYuv(image)
webRTC.ImageChannel <- yuv
}
}
}