rbxcompiler/internal/rbxbuilder/dump_place.go

160 lines
3.2 KiB
Go

package rbxbuilder
import (
"bytes"
"encoding/json"
"git.itzana.me/itzaname/rbxfile"
"git.itzana.me/itzaname/rbxfile/xml"
"io/ioutil"
"os"
"path/filepath"
)
type PlaceDumper struct {
Options *DumpSettings
source *rbxfile.Root
template *rbxfile.Root
scripts map[string]string
}
func (d *PlaceDumper) dumpScriptsFromInstance(instance *rbxfile.Instance) error {
for _, child := range instance.Children {
if isScript(child) {
path := getScriptFilePathString(child)
if child.ClassName != "ModuleScript" {
d.scripts[path] = child.ClassName
}
if err := os.MkdirAll(filepath.Dir(d.Options.Output+path), 0755); err != nil {
return err
}
if err := ioutil.WriteFile(d.Options.Output+path, []byte(getSource(child)), 0644); err != nil {
return err
}
}
if err := d.dumpScriptsFromInstance(child); err != nil {
return err
}
}
return nil
}
func (d *PlaceDumper) findInstance(name string) *rbxfile.Instance {
for _, child := range d.template.Instances {
if child.Name() == name {
return child
}
}
return nil
}
func (d *PlaceDumper) removeScripts(instance *rbxfile.Instance) {
var queue []*rbxfile.Instance
for _, child := range instance.Children {
if isScript(child) {
queue = append(queue, child)
continue
}
d.removeScripts(child)
}
for i := 0; i < len(queue); i++ {
instance.RemoveChild(queue[i])
}
}
func (d *PlaceDumper) addAssets() {
for _, parent := range d.source.Instances {
for _, child := range parent.Children {
if !isScript(child) {
if destInst := d.findInstance(parent.Name()); destInst != nil {
newChild := child.Clone()
d.removeScripts(newChild)
destInst.AddChild(newChild)
}
}
}
}
}
func (d *PlaceDumper) createTemplate() {
d.template = rbxfile.NewRoot()
for _, child := range d.source.Instances {
newInst := child.Clone()
newInst.RemoveAll()
d.template.Instances = append(d.template.Instances, newInst)
}
d.addAssets()
}
func (d *PlaceDumper) loadRootFromFile() error {
file, err := os.Open(d.Options.Source)
if err != nil {
return err
}
root, err := xml.Deserialize(file, nil)
if err != nil {
return err
}
d.source = root
return nil
}
func (d *PlaceDumper) dumpScripts() error {
for i := 0; i < len(d.source.Instances); i++ {
if err := d.dumpScriptsFromInstance(d.source.Instances[i]); err != nil {
return err
}
}
return nil
}
func (d PlaceDumper) writeManifest() error {
buffer := &bytes.Buffer{}
if err := xml.Serialize(buffer, nil, d.template); err != nil {
return err
}
manifest := Manifest{
Template: buffer.Bytes(),
}
for path, class := range d.scripts {
manifest.Override = append(manifest.Override, Script{
Path: path,
Class: class,
})
}
file, err := os.OpenFile(d.Options.Output+seperator+"manifest.json", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
encoder.SetIndent("", "\t")
return encoder.Encode(&manifest)
}
func (d PlaceDumper) Dump() error {
d.scripts = map[string]string{}
if err := d.loadRootFromFile(); err != nil {
return err
}
d.createTemplate()
if err := d.dumpScripts(); err != nil {
return err
}
if err := d.writeManifest(); err != nil {
return err
}
return nil
}