Add system param into the library

This commit is contained in:
Sergey Stepanov 2023-06-02 17:14:08 +03:00 committed by sergystepanov
parent 1f7b5139c6
commit 860c8b9d45
9 changed files with 57 additions and 44 deletions

View file

@ -25,10 +25,11 @@ type (
PlayerIndex int `json:"player_index"`
}
GameInfo struct {
Name string `json:"name"`
Base string `json:"base"`
Path string `json:"path"`
Type string `json:"type"`
Name string `json:"name"`
Base string `json:"base"`
Path string `json:"path"`
System string `json:"system"`
Type string `json:"type"`
}
StartGameResponse struct {
Room

View file

@ -14,7 +14,7 @@ import (
)
func New(conf config.CoordinatorConfig, log *logger.Logger) (services service.Group) {
lib := games.NewLibWhitelisted(conf.Coordinator.Library, conf.Emulator, log)
lib := games.NewLib(conf.Coordinator.Library, conf.Emulator, log)
lib.Scan()
hub := NewHub(conf, lib, log)
h, err := NewHTTPServer(conf, log, func(mux *httpx.Mux) *httpx.Mux {

View file

@ -23,7 +23,7 @@ func (w *Worker) StartGame(id com.Uid, app games.AppMeta, req api.GameStartUserR
return api.UnwrapChecked[api.StartGameResponse](
w.Send(api.StartGame, api.StartGameRequest[com.Uid]{
StatefulRoom: StateRoom(id, req.RoomId),
Game: api.GameInfo{Name: app.Name, Base: app.Base, Path: app.Path, Type: app.Type},
Game: api.GameInfo{Name: app.Name, Base: app.Base, Path: app.Path, System: app.System, Type: app.Type},
PlayerIndex: req.PlayerIndex,
Record: req.Record,
RecordUser: req.RecordUser,

View file

@ -14,10 +14,11 @@ type Launcher interface {
}
type AppMeta struct {
Name string
Type string
Base string
Path string
Name string
Type string
Base string
Path string
System string
}
type GameLauncher struct {
@ -31,7 +32,7 @@ func (gl GameLauncher) FindAppByName(name string) (AppMeta, error) {
if game.Path == "" {
return AppMeta{}, fmt.Errorf("couldn't find game info for the game %v", name)
}
return AppMeta{Name: game.Name, Base: game.Base, Type: game.Type, Path: game.Path}, nil
return AppMeta{Name: game.Name, Base: game.Base, Type: game.Type, Path: game.Path, System: game.System}, nil
}
func (gl GameLauncher) ExtractAppNameFromUrl(name string) string { return ExtractGame(name) }

View file

@ -1,6 +1,7 @@
package games
import (
"fmt"
"io/fs"
"path/filepath"
"strings"
@ -34,6 +35,8 @@ type library struct {
games map[string]GameMetadata
log *logger.Logger
emuConf WithEmulatorInfo
// to restrict parallel execution or throttling
// for file watch mode
mu sync.Mutex
@ -47,8 +50,9 @@ type GameLibrary interface {
Scan()
}
type FileExtensionWhitelist interface {
type WithEmulatorInfo interface {
GetSupportedExtensions() []string
GetEmulator(rom string, path string) string
}
type GameMetadata struct {
@ -58,7 +62,8 @@ type GameMetadata struct {
Type string
Base string
// the game path relative to the library base path
Path string
Path string
System string
}
func (g GameMetadata) FullPath(base string) string {
@ -68,11 +73,7 @@ func (g GameMetadata) FullPath(base string) string {
return filepath.Join(base, g.Path)
}
func NewLib(conf config.Library, log *logger.Logger) GameLibrary {
return NewLibWhitelisted(conf, conf, log)
}
func NewLibWhitelisted(conf config.Library, filter FileExtensionWhitelist, log *logger.Logger) GameLibrary {
func NewLib(conf config.Library, emu WithEmulatorInfo, log *logger.Logger) GameLibrary {
hasSource := true
dir, err := filepath.Abs(conf.BasePath)
if err != nil {
@ -81,7 +82,7 @@ func NewLibWhitelisted(conf config.Library, filter FileExtensionWhitelist, log *
}
if len(conf.Supported) == 0 {
conf.Supported = filter.GetSupportedExtensions()
conf.Supported = emu.GetSupportedExtensions()
}
library := &library{
@ -96,6 +97,7 @@ func NewLibWhitelisted(conf config.Library, filter FileExtensionWhitelist, log *
games: map[string]GameMetadata{},
hasSource: hasSource,
log: log,
emuConf: emu,
}
if conf.WatchMode && hasSource {
@ -152,6 +154,9 @@ func (lib *library) Scan() {
if info != nil && !info.IsDir() && lib.isExtAllowed(path) {
meta := getMetadata(path, dir)
meta.System = lib.emuConf.GetEmulator(meta.Type, meta.Path)
if _, ok := lib.config.ignored[meta.Name]; !ok {
games = append(games, meta)
}
@ -258,7 +263,7 @@ func getMetadata(path string, basePath string) GameMetadata {
func (lib *library) dumpLibrary() {
var gameList strings.Builder
for _, game := range lib.games {
gameList.WriteString(" " + game.Name + " (" + game.Path + ")" + "\n")
gameList.WriteString(fmt.Sprintf(" %5s %s (%s)\n", game.System, game.Name, game.Path))
}
lib.log.Debug().Msgf("Lib dump\n"+

View file

@ -10,32 +10,44 @@ import (
func TestLibraryScan(t *testing.T) {
tests := []struct {
directory string
expected []string
expected []struct {
name string
system string
}
}{
{
directory: "../../assets/games",
expected: []string{
"Alwa's Awakening (Demo)", "Sushi The Cat", "anguna",
expected: []struct {
name string
system string
}{
{name: "Alwa's Awakening (Demo)", system: "nes"},
{name: "Sushi The Cat", system: "gba"},
{name: "anguna", system: "gba"},
},
},
}
emuConf := config.Emulator{Libretro: config.LibretroConfig{}}
emuConf.Libretro.Cores.List = map[string]config.LibretroCoreConfig{
"nes": {Roms: []string{"nes"}},
"gba": {Roms: []string{"gba"}},
}
l := logger.NewConsole(false, "w", false)
for _, test := range tests {
library := NewLib(config.Library{
BasePath: test.directory,
Supported: []string{"gba", "zip", "nes"},
}, l)
}, emuConf, l)
library.Scan()
games := library.GetAll()
list := _map(games, func(g GameMetadata) string { return g.Name })
all := true
for _, expect := range test.expected {
found := false
for _, game := range list {
if game == expect {
for _, game := range games {
if game.Name == expect.name && (expect.system != "" && expect.system == game.System) {
found = true
break
}
@ -43,7 +55,7 @@ func TestLibraryScan(t *testing.T) {
all = all && found
}
if !all {
t.Errorf("Test fail for dir %v with %v != %v", test.directory, list, test.expected)
t.Errorf("Test fail for dir %v with %v != %v", test.directory, games, test.expected)
}
}
}
@ -54,18 +66,10 @@ func Benchmark(b *testing.B) {
library := NewLib(config.Library{
BasePath: "../../assets/games",
Supported: []string{"gba", "zip", "nes"},
}, log)
}, config.Emulator{}, log)
for i := 0; i < b.N; i++ {
library.Scan()
_ = library.GetAll()
}
}
func _map(vs []GameMetadata, f func(info GameMetadata) string) []string {
vsm := make([]string, len(vs))
for i, v := range vs {
vsm[i] = f(v)
}
return vsm
}

View file

@ -81,7 +81,9 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
if room == nil {
room = NewRoom(
rq.Room.Rid,
games.GameMetadata{Name: rq.Game.Name, Base: rq.Game.Base, Type: rq.Game.Type, Path: rq.Game.Path},
games.GameMetadata{
Name: rq.Game.Name, Base: rq.Game.Base, Type: rq.Game.Type, Path: rq.Game.Path, System: rq.Game.System,
},
func(room *Room) {
w.router.SetRoom(nil)
c.CloseRoom(room.id)

View file

@ -55,7 +55,7 @@ func NewRoom(id string, game games.GameMetadata, onClose func(*Room), conf confi
}
room.emulator = nano
room.emulator.SetMainSaveName(id)
room.emulator.LoadMetadata(conf.Emulator.GetEmulator(game.Type, game.Path))
room.emulator.LoadMetadata(game.System)
err = room.emulator.LoadGame(game.FullPath(conf.Worker.Library.BasePath))
if err != nil {
log.Fatal().Err(err).Msgf("couldn't load the game %v", game)

View file

@ -43,7 +43,7 @@ type roomMock struct {
func (rm roomMock) Close() {
rm.Room.Close()
// hack: wait room destruction
time.Sleep(3 * time.Second)
time.Sleep(2 * time.Second)
}
func (rm roomMock) CloseNowait() { rm.Room.Close() }
@ -64,9 +64,9 @@ var testTempDir = filepath.Join(os.TempDir(), "cloud-game-core-tests")
// games
var (
alwas = games.GameMetadata{Name: "Alwa's Awakening (Demo)", Type: "nes", Path: "Alwa's Awakening (Demo).nes"}
sushi = games.GameMetadata{Name: "Sushi The Cat", Type: "gba", Path: "Sushi The Cat.gba"}
fd = games.GameMetadata{Name: "Florian Demo", Type: "n64", Path: "Sample Demo by Florian (PD).z64"}
alwas = games.GameMetadata{Name: "Alwa's Awakening (Demo)", Type: "nes", Path: "Alwa's Awakening (Demo).nes", System: "nes"}
sushi = games.GameMetadata{Name: "Sushi The Cat", Type: "gba", Path: "Sushi The Cat.gba", System: "gba"}
fd = games.GameMetadata{Name: "Florian Demo", Type: "n64", Path: "Sample Demo by Florian (PD).z64", System: "n64"}
)
func init() {