rbxcompiler/internal/rbxbuilder/build_place.go

161 lines
3.7 KiB
Go
Raw Normal View History

2020-09-29 20:58:00 +00:00
package rbxbuilder
import (
"bytes"
"encoding/json"
"fmt"
2021-08-11 00:16:40 +00:00
"git.itzana.me/itzaname/rbxfile"
"git.itzana.me/itzaname/rbxfile/xml"
2020-09-29 20:58:00 +00:00
"os"
"path/filepath"
"sort"
"strings"
)
type PlaceBuilder struct {
Options *BuildSettings
root *rbxfile.Root
scripts map[string]string
}
func (b *PlaceBuilder) loadScript(path string) error {
scriptName := strings.TrimSuffix(filepath.Base(path), ".lua")
parentPath := filepath.Dir(path)
parentName := filepath.Base(parentPath)
basePath := strings.TrimSuffix(strings.TrimSuffix(path, parentName+string(os.PathSeparator)+filepath.Base(path)), seperator)
if basePath == "" {
basePath = parentPath
}
parentInstance := instanceFromScriptPath(b.root, parentPath)
parentBaseInstance := instanceFromScriptPath(b.root, basePath)
if parentBaseInstance == nil {
return fmt.Errorf("base instance doesn't exist: %s", basePath)
}
if parentInstance == nil {
class := "ModuleScript"
path := parentPath + seperator + parentName + ".lua"
if override, ok := b.scripts[path]; ok {
class = override
}
script := loadScript(parentName, class, b.Options.Source+path)
if script != nil {
if err := parentBaseInstance.AddChild(script); err != nil {
return err
}
parentInstance = script
} else {
if err := parentBaseInstance.AddChild(generateFolder(parentName)); err != nil {
return err
}
parentInstance = script
}
}
if scriptName == parentName {
return nil
}
// Load normal scripts
class := "ModuleScript"
if override, ok := b.scripts[path]; ok {
class = override
}
script := loadScript(scriptName, class, b.Options.Source+path)
if script != nil {
if err := parentInstance.AddChild(script); err != nil {
return err
}
} else {
return fmt.Errorf("failed to load script: %s", path)
}
return nil
}
func (b *PlaceBuilder) scriptTree() ([]string, error) {
var filelist []string
err := filepath.Walk(b.Options.Source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
if filepath.Ext(path) == ".lua" {
filelist = append(filelist, strings.TrimPrefix(path, b.Options.Source))
}
}
return nil
})
sort.Slice(filelist, func(i, j int) bool {
return strings.Count(filelist[i], string(os.PathSeparator)) < strings.Count(filelist[j], string(os.PathSeparator))
})
return filelist, err
}
func (b *PlaceBuilder) createScripts() error {
tree, err := b.scriptTree()
if err != nil {
return err
}
for i := 0; i < len(tree); i++ {
if err := b.loadScript(tree[i]); err != nil {
return err
}
}
return nil
}
func (b *PlaceBuilder) loadManifest() error {
b.scripts = map[string]string{}
file, err := os.Open(b.Options.Source + seperator + "manifest.json")
if err != nil {
return fmt.Errorf("failed to load manifest file")
}
defer file.Close()
var manifest Manifest
if err := json.NewDecoder(file).Decode(&manifest); err != nil {
return fmt.Errorf("failed to load manifest file")
}
for i := 0; i < len(manifest.Override); i++ {
b.scripts[manifest.Override[i].Path] = manifest.Override[i].Class
}
buffer := bytes.NewBuffer(manifest.Template)
root, err := xml.Deserialize(buffer, nil)
if err != nil {
return fmt.Errorf("failed to load template from manifest")
}
b.root = root
return nil
}
func (b PlaceBuilder) Build() error {
if err := b.loadManifest(); err != nil {
return err
}
if err := b.createScripts(); err != nil {
return err
}
2020-09-29 22:25:53 +00:00
if b.Options.Writer != nil {
return xml.Serialize(b.Options.Writer, nil, b.root)
}
2020-09-29 20:58:00 +00:00
file, err := os.OpenFile(b.Options.Output, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("failed to open output file")
}
defer file.Close()
return xml.Serialize(file, nil, b.root)
}