Noah Petherbridge
b17ca34de2
* Use `go-bindata` to embed built-in doodads and levels directly into the Doodle binary. `make bindata` produces the bindata source file. * Add `FromJSON()` method to Levels and Doodads to load objects from JSON strings in memory (for bindata built-ins or WASM ajax requests) * Update file loading functions to check the embedded bindata files. * pkg/config.go#EditFile: * Supports editing a level from bindata (TODO: remove this support) * If the "assets/levels/%(simple-name.level)" exists in bindata, edits that drawing. * No such support for editing built-in doodads. * WASM has no filesystem access to edit files except built-in levels (yet) * pkg/doodads#ListDoodads: * Prepends built-in doodads from bindata to the returned list. * WASM: no filesystem access so gets only the built-ins. * pkg/doodads#LoadFile: * Checks built-in bindata store first for doodad files. * WASM: tries an HTTP request if not found in bindata but can go no further if not found (no filesystem access) * pkg/filesystem#FindFile: * This function finds a level/doodad by checking all the places. * If the level or doodad exists in bindata built-in, always returns its system path like "assets/doodads/test.doodad" * WASM: always returns the built-in candidate path even if not found in bindata so that ajax GET can be attempted. * pkg/level#ListSystemLevels: * New function that lists the system level files, similar to the equivalent doodads function. * Prepends the bindata built-in level files. * WASM: only returns the built-ins (no filesystem support) * Desktop: also lists and returns the assets/levels/ directory. * pkg/level#LoadFile: * Like the doodads.LoadFile, tries from built-in bindata first, then ajax request (WASM) before accessing the filesystem (desktop) * Menu Scene: TODO, list the built-in levels in the Load Level menu. This feature will soon go away when WASM gets its own storage for user levels (localStorage instead of filesystem)
117 lines
2.6 KiB
Go
117 lines
2.6 KiB
Go
package level
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"git.kirsle.net/apps/doodle/pkg/bindata"
|
|
"git.kirsle.net/apps/doodle/pkg/branding"
|
|
"git.kirsle.net/apps/doodle/pkg/enum"
|
|
"git.kirsle.net/apps/doodle/pkg/filesystem"
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
|
"git.kirsle.net/apps/doodle/pkg/userdir"
|
|
"git.kirsle.net/apps/doodle/pkg/wasm"
|
|
)
|
|
|
|
// ListSystemLevels returns a list of built-in levels.
|
|
func ListSystemLevels() ([]string, error) {
|
|
var names = []string{}
|
|
|
|
// Add the levels embedded inside the binary.
|
|
if levels, err := bindata.AssetDir("assets/levels"); err == nil {
|
|
names = append(names, levels...)
|
|
}
|
|
|
|
// WASM
|
|
if runtime.GOOS == "js" {
|
|
// Return just the embedded ones, no filesystem access.
|
|
return names, nil
|
|
}
|
|
|
|
// Read filesystem for system levels.
|
|
files, err := ioutil.ReadDir(filesystem.SystemLevelsPath)
|
|
for _, file := range files {
|
|
name := file.Name()
|
|
if strings.HasSuffix(strings.ToLower(name), enum.DoodadExt) {
|
|
names = append(names, name)
|
|
}
|
|
}
|
|
|
|
return names, err
|
|
}
|
|
|
|
// LoadFile reads a level file from disk, checking a few locations.
|
|
func LoadFile(filename string) (*Level, error) {
|
|
if !strings.HasSuffix(filename, enum.LevelExt) {
|
|
filename += enum.LevelExt
|
|
}
|
|
|
|
// Search the system and user paths for this level.
|
|
filename, err := filesystem.FindFile(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Do we have the file in bindata?
|
|
if jsonData, err := bindata.Asset(filename); err == nil {
|
|
log.Info("loaded from embedded bindata")
|
|
return FromJSON(filename, jsonData)
|
|
}
|
|
|
|
// WASM: try the file over HTTP ajax request.
|
|
if runtime.GOOS == "js" {
|
|
jsonData, err := wasm.HTTPGet(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return FromJSON(filename, jsonData)
|
|
}
|
|
|
|
// Try the binary format.
|
|
if level, err := LoadBinary(filename); err == nil {
|
|
return level, nil
|
|
} else {
|
|
log.Warn(err.Error())
|
|
}
|
|
|
|
// Then the JSON format.
|
|
if level, err := LoadJSON(filename); err == nil {
|
|
return level, nil
|
|
} else {
|
|
log.Warn(err.Error())
|
|
}
|
|
|
|
return nil, errors.New("invalid file type")
|
|
}
|
|
|
|
// WriteFile saves a level to disk in the user's config directory.
|
|
func (m *Level) WriteFile(filename string) error {
|
|
if !strings.HasSuffix(filename, enum.LevelExt) {
|
|
filename += enum.LevelExt
|
|
}
|
|
|
|
// Set the version information.
|
|
m.Version = 1
|
|
m.GameVersion = branding.Version
|
|
|
|
// bin, err := m.ToBinary()
|
|
bin, err := m.ToJSON()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Save it to their profile directory.
|
|
filename = userdir.LevelPath(filename)
|
|
log.Info("Write Level: %s", filename)
|
|
err = ioutil.WriteFile(filename, bin, 0644)
|
|
if err != nil {
|
|
return fmt.Errorf("level.WriteFile: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|