func (inst *Instance) Get(property string) (value Value) {
	return inst.Properties[property]
}
Get returns the value of a property in the instance. The value will be nil
if the property is not defined.
package rbxfile
import (
	"errors"
)
type Root struct {
	Instances []*Instance
	Metadata map[string]string
}
func NewRoot() *Root {
	return &Root{
		Instances: []*Instance{},
		Metadata:  map[string]string{},
	}
}
func (root *Root) Copy() *Root {
	clone := &Root{
		Instances: make([]*Instance, len(root.Instances)),
	}
	refs := make(References)
	crefs := make(References)
	propRefs := make([]PropRef, 0, 8)
	for i, inst := range root.Instances {
		clone.Instances[i] = inst.clone(refs, crefs, &propRefs)
	}
	for _, propRef := range propRefs {
		if !crefs.Resolve(propRef) {
			refs.Resolve(propRef)
		}
	}
	return clone
}
type Instance struct {
	ClassName string
	Reference string
	IsService bool
	Properties map[string]Value
	Children []*Instance
	parent *Instance
}
func NewInstance(className string, parent *Instance) *Instance {
	inst := &Instance{
		ClassName:  className,
		Reference:  GenerateReference(),
		Properties: make(map[string]Value, 0),
	}
	if parent != nil {
		parent.Children = append(parent.Children, inst)
		inst.parent = parent
	}
	return inst
}
func assertLoop(child, parent *Instance) error {
	if parent == child {
		return errors.New("attempt to set instance as its own parent")
	}
	if parent != nil && parent.IsDescendantOf(child) {
		return errors.New("attempt to set parent would result in circular reference")
	}
	return nil
}
func (inst *Instance) addChild(child *Instance) {
	if child.parent != nil {
		child.parent.RemoveChild(child)
	}
	inst.Children = append(inst.Children, child)
	child.parent = inst
}
func (inst *Instance) AddChild(child *Instance) error {
	if err := assertLoop(child, inst); err != nil {
		return err
	}
	inst.addChild(child)
	return nil
}
func (inst *Instance) AddChildAt(index int, child *Instance) error {
	if err := assertLoop(child, inst); err != nil {
		return err
	}
	if index < 0 {
		index = 0
	} else if index >= len(inst.Children) {
		inst.addChild(child)
		return nil
	}
	if child.parent != nil {
		child.parent.RemoveChild(child)
	}
	inst.Children = append(inst.Children, nil)
	copy(inst.Children[index+1:], inst.Children[index:])
	inst.Children[index] = child
	child.parent = inst
	return nil
}
func (inst *Instance) removeChildAt(index int) (child *Instance) {
	child = inst.Children[index]
	child.parent = nil
	copy(inst.Children[index:], inst.Children[index+1:])
	inst.Children[len(inst.Children)-1] = nil
	inst.Children = inst.Children[:len(inst.Children)-1]
	return child
}
func (inst *Instance) RemoveChild(child *Instance) *Instance {
	for index, c := range inst.Children {
		if c == child {
			return inst.removeChildAt(index)
		}
	}
	return nil
}
func (inst *Instance) RemoveChildAt(index int) *Instance {
	if index < 0 || index >= len(inst.Children) {
		return nil
	}
	return inst.removeChildAt(index)
}
func (inst *Instance) RemoveAll() {
	for i, child := range inst.Children {
		child.parent = nil
		inst.Children[i] = nil
	}
	inst.Children = inst.Children[:0]
}
func (inst *Instance) Parent() *Instance {
	return inst.parent
}
func (inst *Instance) SetParent(parent *Instance) error {
	if inst.parent == parent {
		return nil
	}
	if err := assertLoop(inst, parent); err != nil {
		return err
	}
	if inst.parent != nil {
		inst.parent.RemoveChild(inst)
	}
	if parent != nil {
		parent.addChild(inst)
	}
	return nil
}
func (inst *Instance) FixTree() {
	for i := 0; i < len(inst.Children); {
		child := inst.Children[i]
		if err := assertLoop(child, inst); err != nil {
			inst.removeChildAt(i)
			continue
		}
		child.parent = inst
		child.FixTree()
		i++
	}
}
func (inst *Instance) clone(refs, crefs References, propRefs *[]PropRef) *Instance {
	clone := &Instance{
		ClassName:  inst.ClassName,
		Reference:  refs.Get(inst),
		IsService:  inst.IsService,
		Children:   make([]*Instance, len(inst.Children)),
		Properties: make(map[string]Value, len(inst.Properties)),
	}
	crefs[clone.Reference] = clone
	for name, value := range inst.Properties {
		if value, ok := value.(ValueReference); ok {
			*propRefs = append(*propRefs, PropRef{
				Instance:  clone,
				Property:  name,
				Reference: refs.Get(value.Instance),
			})
			continue
		}
		clone.Properties[name] = value.Copy()
	}
	for i, child := range inst.Children {
		c := child.clone(refs, crefs, propRefs)
		clone.Children[i] = c
		c.parent = clone
	}
	return clone
}
func (inst *Instance) Clone() *Instance {
	refs := make(References)
	crefs := make(References)
	propRefs := make([]PropRef, 0, 8)
	clone := inst.clone(refs, crefs, &propRefs)
	for _, propRef := range propRefs {
		if !crefs.Resolve(propRef) {
			refs.Resolve(propRef)
		}
	}
	return clone
}
func (inst *Instance) FindFirstChild(name string, recursive bool) *Instance {
	for _, child := range inst.Children {
		if child.Name() == name {
			return child
		}
	}
	if recursive {
		for _, child := range inst.Children {
			if desc := child.FindFirstChild(name, true); desc != nil {
				return desc
			}
		}
	}
	return nil
}
func (inst *Instance) GetFullName() string {
	names := make([]string, 0, 8)
	object := inst
	for object != nil {
		names = append(names, object.Name())
		object = object.Parent()
	}
	full := make([]byte, 0, 64)
	for i := len(names) - 1; i > 0; i-- {
		full = append(full, []byte(names[i])...)
		full = append(full, '.')
	}
	full = append(full, []byte(names[0])...)
	return string(full)
}
func (inst *Instance) IsAncestorOf(descendant *Instance) bool {
	if descendant != nil {
		return descendant.IsDescendantOf(inst)
	}
	return false
}
func (inst *Instance) IsDescendantOf(ancestor *Instance) bool {
	parent := inst.Parent()
	for parent != nil {
		if parent == ancestor {
			return true
		}
		parent = parent.Parent()
	}
	return false
}
func (inst *Instance) Name() string {
	iname, ok := inst.Properties["Name"]
	if !ok {
		return ""
	}
	name, _ := iname.(ValueString)
	return string(name)
}
func (inst *Instance) String() string {
	iname, ok := inst.Properties["Name"]
	if !ok {
		return inst.ClassName
	}
	name, _ := iname.(ValueString)
	if string(name) == "" {
		return inst.ClassName
	}
	return string(name)
}
func (inst *Instance) SetName(name string) {
	inst.Properties["Name"] = ValueString(name)
}