From 08f9654dd56c098259db11450dda0467aa19666d Mon Sep 17 00:00:00 2001 From: giongto35 Date: Sun, 5 May 2019 23:19:47 +0800 Subject: [PATCH] Load game from GCP --- emulator/director.go | 13 +++++++-- emulator/gameview.go | 10 ++++--- emulator/util.go | 6 ++++ handler/room/room.go | 68 ++++++++++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/emulator/director.go b/emulator/director.go index 770e5227..3ca6bd9e 100644 --- a/emulator/director.go +++ b/emulator/director.go @@ -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 diff --git a/emulator/gameview.go b/emulator/gameview.go index 28051fa8..05f3d70c 100644 --- a/emulator/gameview.go +++ b/emulator/gameview.go @@ -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 } } diff --git a/emulator/util.go b/emulator/util.go index 79cbec16..029558ff 100644 --- a/emulator/util.go +++ b/emulator/util.go @@ -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" } diff --git a/handler/room/room.go b/handler/room/room.go index 2797a755..2d0aa432 100644 --- a/handler/room/room.go +++ b/handler/room/room.go @@ -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 }