Noah Petherbridge
a75b7208ca
Adds `doodad levelpack create` and `doodad levelpack show` commands to the CLI tool to create levelpacks. A levelpack is a ZIP file containing a descriptive index.json and directories for levels and doodads.
113 lines
2.4 KiB
Go
113 lines
2.4 KiB
Go
// Package levelpack handles ZIP archives for level packs.
|
|
package levelpack
|
|
|
|
import (
|
|
"archive/zip"
|
|
"encoding/json"
|
|
"errors"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// LevelPack describes the contents of a levelpack file.
|
|
type LevelPack struct {
|
|
Title string `json:"title`
|
|
Description string `json:"description"`
|
|
Author string `json:"author"`
|
|
Created time.Time `json:"created"`
|
|
|
|
// Cached metadata about the (displayed) levels.
|
|
Levels []Level `json:"levels"`
|
|
|
|
// Number of levels unlocked by default.
|
|
// 0 = all levels unlocked
|
|
FreeLevels int `json:"freeLevels"`
|
|
|
|
// The loaded zip file for reading an existing levelpack.
|
|
Zipfile *zip.Reader `json:"-"`
|
|
}
|
|
|
|
// Level holds metadata about the levels in the levelpack.
|
|
type Level struct {
|
|
Title string `json:"title"`
|
|
Author string `json:"author"`
|
|
Filename string `json:"filename"`
|
|
}
|
|
|
|
// LoadFile reads a .levelpack zip file.
|
|
func LoadFile(filename string) (LevelPack, error) {
|
|
stat, err := os.Stat(filename)
|
|
if err != nil {
|
|
return LevelPack{}, err
|
|
}
|
|
|
|
fh, err := os.Open(filename)
|
|
if err != nil {
|
|
return LevelPack{}, err
|
|
}
|
|
|
|
reader, err := zip.NewReader(fh, stat.Size())
|
|
if err != nil {
|
|
return LevelPack{}, err
|
|
}
|
|
|
|
lp := LevelPack{
|
|
Zipfile: reader,
|
|
}
|
|
|
|
// Read the index.json.
|
|
lp.GetJSON(&lp, "index.json")
|
|
|
|
return lp, nil
|
|
}
|
|
|
|
// WriteFile saves the metadata to a .json file on disk.
|
|
func (l LevelPack) WriteFile(filename string) error {
|
|
out, err := json.Marshal(l)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ioutil.WriteFile(filename, out, 0655)
|
|
}
|
|
|
|
// GetData returns file data from inside the loaded zipfile of a levelpack.
|
|
func (l LevelPack) GetData(filename string) ([]byte, error) {
|
|
if l.Zipfile == nil {
|
|
return []byte{}, errors.New("zipfile not loaded")
|
|
}
|
|
|
|
file, err := l.Zipfile.Open(filename)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
return ioutil.ReadAll(file)
|
|
}
|
|
|
|
// GetJSON loads a JSON file from the zipfile and marshals it into your struct.
|
|
func (l LevelPack) GetJSON(v interface{}, filename string) error {
|
|
data, err := l.GetData(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return json.Unmarshal(data, v)
|
|
}
|
|
|
|
// ListFiles returns the files in the zipfile that match the prefix given.
|
|
func (l LevelPack) ListFiles(prefix string) []string {
|
|
var result []string
|
|
|
|
if l.Zipfile != nil {
|
|
for _, file := range l.Zipfile.File {
|
|
if strings.HasPrefix(file.Name, prefix) {
|
|
result = append(result, file.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|