Load game from GCP

This commit is contained in:
giongto35 2019-05-05 23:19:47 +08:00
parent c08daf2151
commit 08f9654dd5
4 changed files with 69 additions and 28 deletions

View file

@ -3,6 +3,7 @@ package emulator
import (
"image"
"log"
"os"
"time"
"github.com/giongto35/cloud-game/emulator/nes"
@ -97,7 +98,7 @@ L:
}
func (d *Director) PlayGame(path string) {
// Generate hash that is indentifier of a room (game path + ropomID)
// Generate hash that is indentifier of a room (game path + roomID)
hash, err := hashFile(path, d.roomID)
if err != nil {
log.Fatalln(err)
@ -111,6 +112,12 @@ func (d *Director) PlayGame(path string) {
d.SetView(NewGameView(console, path, hash, d.imageChannel, d.audioChannel, d.inputChannel))
}
func (d *Director) IsGameOnLocal(path string, roomID string) bool {
hash, _ := hashFile(path, roomID)
_, err := os.Open(savePath(hash))
return err != nil
}
// SaveGame creates save events and doing extra step for load
func (d *Director) SaveGame(saveExtraFunc func() error) error {
if d.hash != "" {
@ -122,9 +129,9 @@ func (d *Director) SaveGame(saveExtraFunc func() error) error {
}
// LoadGame creates load events and doing extra step for load
func (d *Director) LoadGame(loadExtraFunc func() error) error {
func (d *Director) LoadGame() error {
if d.hash != "" {
d.view.Load(d.hash, loadExtraFunc)
d.view.Load(d.hash)
return nil
} else {
return nil

View file

@ -99,7 +99,7 @@ func (view *GameView) Enter() {
view.console.SetAudioSampleRate(SampleRate)
view.console.SetAudioChannel(view.audioChannel)
// load state if the hash file existed (Join the old room)
// load state if the hash file existed in the server (Join the old room)
if err := view.console.LoadState(savePath(view.hash)); err == nil {
return
} else {
@ -149,11 +149,11 @@ func (view *GameView) Save(hash string, extraSaveFunc func() error) {
}
}
func (view *GameView) Load(path string, extraLoadFunc func() error) {
func (view *GameView) Load(path string) {
// put saving event to queue, process in updateEvent
view.loadingJob = &job{
path: savePath(view.hash),
extraFunc: extraLoadFunc,
extraFunc: nil,
}
}
@ -169,7 +169,9 @@ func (view *GameView) UpdateEvents() {
if view.loadingJob != nil {
view.console.LoadState(view.loadingJob.path)
// Run extra function (online saving for example)
go view.loadingJob.extraFunc()
if view.loadingJob.extraFunc != nil {
go view.loadingJob.extraFunc()
}
view.loadingJob = nil
}
}

View file

@ -33,6 +33,12 @@ func sramPath(hash string) string {
return homeDir + "/.nes/sram/" + hash + ".dat"
}
// Public call to get savePath
func GetSavePath(path string, roomID string) string {
hash, _ := hashFile(path, roomID)
return savePath(hash)
}
func savePath(hash string) string {
return homeDir + "/.nes/save/" + hash + ".dat"
}

View file

@ -6,6 +6,7 @@ import (
"io/ioutil"
"log"
"math/rand"
"os"
"strconv"
"sync"
@ -63,7 +64,22 @@ func NewRoom(roomID, gamepath, gameName string, onlineStorage *storage.Client) *
go room.startVideo()
go room.startAudio()
go director.Start([]string{gamepath + "/" + gameName})
path := gamepath + "/" + gameName
go func(path, roomID string) {
// Check room is on local or fetch from server
savepath := emulator.GetSavePath(path, roomID)
log.Println("Check ", savepath, " on local : ", room.isGameOnLocal(savepath))
if !room.isGameOnLocal(savepath) {
// Fetch room from GCP to server
log.Println("Load room from online storage", savepath)
if err := room.loadRoomOnline(roomID, savepath); err != nil {
log.Printf("Warn: Room %s is not in online storage, error %s", roomID, err)
}
}
director.Start([]string{path})
}(path, roomID)
return room
}
@ -76,6 +92,11 @@ func generateRoomID() string {
return roomID
}
func (r *Room) isGameOnLocal(savepath string) bool {
_, err := os.Open(savepath)
return err == nil
}
func (r *Room) AddConnectionToRoom(peerconnection *webrtc.WebRTC, playerIndex int) {
peerconnection.AttachRoomID(r.ID)
r.rtcSessions = append(r.rtcSessions, peerconnection)
@ -112,6 +133,9 @@ func (r *Room) startWebRTCSession(peerconnection *webrtc.WebRTC, playerIndex int
func (r *Room) CleanSession(peerconnection *webrtc.WebRTC) {
r.removeSession(peerconnection)
// TODO: Clean all channels
//close(peerconnection.ImageChannel)
//close(peerconnection.AudioChannel)
//close(peerconnection.InputChannel)
}
func (r *Room) removeSession(w *webrtc.WebRTC) {
@ -138,12 +162,15 @@ func (r *Room) removeSession(w *webrtc.WebRTC) {
func (r *Room) Close() {
log.Println("Closing room", r)
r.director.Done <- struct{}{}
//close(r.inputChannel)
//close(r.imageChannel)
//close(r.audioChannel)
}
func (r *Room) SaveGame() error {
onlineSaveFunc := func() error {
// Try to save the game to gCloud
if err := r.onlineStorage.SaveFile(r.director.GetHash(), r.director.GetHashPath()); err != nil {
if err := r.onlineStorage.SaveFile(r.ID, r.director.GetHashPath()); err != nil {
return err
}
@ -158,27 +185,26 @@ func (r *Room) SaveGame() error {
return nil
}
func (r *Room) LoadGame() error {
// TODO: Fix, because load game always come to local, this logic is unnecessary. Move to load game
onlineLoadFunc := func() error {
log.Println("Loading game from cloud storage")
// If the game is not on local server
// Try to load from gcloud
data, err := r.onlineStorage.LoadFile(r.director.GetHash())
if err != nil {
return err
}
// Save the data fetched from gcloud to local server
ioutil.WriteFile(r.director.GetHashPath(), data, 0644)
// Reload game again
//err = r.director.LoadGame(nil)
//if err != nil {
//return err
//}
return nil
func (r *Room) loadRoomOnline(roomID string, savepath string) error {
log.Println("Loading game from cloud storage")
// If the game is not on local server
// Try to load from gcloud
data, err := r.onlineStorage.LoadFile(roomID)
if err != nil {
return err
}
// Save the data fetched from gcloud to local server
ioutil.WriteFile(savepath, data, 0644)
// Reload game again
//err = r.director.LoadGame(nil)
//if err != nil {
//return err
//}
return nil
}
err := r.director.LoadGame(onlineLoadFunc)
func (r *Room) LoadGame() error {
err := r.director.LoadGame()
return err
}