package main import "fmt" type Ship struct { node *Node // Node pointer, for Update Model string Name string Sprite Sprite // TODO: Make this a struct Thumbnail string UUID string // We should not allow this to be changed (it might be significant to Endless Sky) Attributes Attributes Outfits OutfitList Crew int Fuel int Shields int Hull int Pos Vec2 Engines []Engine Guns []Gun Turrets []Turret Leak []string // TODO: Make this a struct Explode []string // TODO: Make this a struct Location Location } func (s *Ship) Type() string { return "Ship" } func (s *Ship) Parse(node *Node) error { if node.Key() != "ship" { return fmt.Errorf("expected 'ship' node, invalid node") } s.node = node s.Model = node.Value() s.Attributes = Attributes{ Others: make(map[string]float64), } s.Engines = []Engine{} s.Guns = []Gun{} s.Turrets = []Turret{} s.Outfits = OutfitList{} for _, kid := range node.Children { switch kid.Key() { case "name": s.Name = kid.Value() case "sprite": err := s.Sprite.Parse(kid) if err != nil { return err } case "thumbnail": s.Thumbnail = kid.Value() case "uuid": s.UUID = kid.Value() case "attributes": err := s.Attributes.Parse(kid) if err != nil { return err } case "outfits": err := s.Outfits.Parse(kid) if err != nil { return err } case "crew": s.Crew = kid.ValueInt() case "fuel": s.Fuel = kid.ValueInt() case "shields": s.Shields = kid.ValueInt() case "hull": s.Hull = kid.ValueInt() case "position": err := s.Pos.Parse(kid.Value()) if err != nil { return err } case "engine": e := Engine{} err := e.Parse(kid) if err != nil { return err } s.Engines = append(s.Engines, e) case "gun": g := Gun{} err := g.Parse(kid) if err != nil { return err } s.Guns = append(s.Guns, g) case "turret": t := Turret{} err := t.Parse(kid) if err != nil { return err } s.Turrets = append(s.Turrets, t) case "leak": s.Leak = append(s.Leak, kid.Value()) case "explode": s.Explode = append(s.Explode, kid.Value()) case "system": if s.Location.System == "" { s.Location.Parse(kid) } case "planet": if s.Location.Planet == "" { s.Location.Parse(kid) } } } return nil } func (s *Ship) Update() error { if s.node == nil { return fmt.Errorf("no node, ship") } s.node.SetValue(s.Model) err := s.Location.Update() if err != nil { return fmt.Errorf("ship, %v", err) } for _, kid := range s.node.Children { switch kid.Key() { case "name": kid.SetValue(s.Name) case "sprite": err := s.Sprite.Update() if err != nil { return err } case "thumbnail": kid.SetValue(s.Thumbnail) case "attributes": err := s.Attributes.Update() if err != nil { return err } case "outfits": err := s.Outfits.Update() if err != nil { return err } case "crew": kid.SetValue(s.Crew) case "fuel": kid.SetValue(s.Fuel) case "shields": kid.SetValue(s.Shields) case "hull": kid.SetValue(s.Hull) case "position": kid.SetValue(s.Pos.String()) case "engine": _, err := kid.DetachFromParent() if err != nil { return err } case "gun": _, err := kid.DetachFromParent() if err != nil { return err } case "turret": _, err := kid.DetachFromParent() if err != nil { return err } } } for _, e := range s.Engines { n := s.node.NewChild() n.Set(e.Kind, e.Pos.String()) n1 := n.NewChild() n1.Set("zoom", e.Zoom) n1 = n.NewChild() n1.Set("angle", e.Angle) if e.Over { n1 = n.NewChild() n1.Line = "over" } else { n1 = n.NewChild() n1.Line = "under" } } for _, g := range s.Guns { n := s.node.NewChild() if g.Mount != "" { n.Set("gun", fmt.Sprintf("%s %s", g.Pos.String(), g.Mount)) } else { n.Set("gun", g.Pos.String()) } if g.Over { n1 := n.NewChild() n1.Line = "over" } else { n1 := n.NewChild() n1.Line = "under" } } for _, t := range s.Turrets { n := s.node.NewChild() if t.Mount != "" { n.Set("turret", fmt.Sprintf("%s %s", t.Pos.String(), t.Mount)) } else { n.Set("turret", t.Pos.String()) } if t.Over { n1 := n.NewChild() n1.Line = "over" } else { n1 := n.NewChild() n1.Line = "under" } } return nil }