package sets import ( "fmt" "io/ioutil" "path/filepath" "strconv" "strings" "ur.gs/chaos-gate/internal/util/asciiscan" ) type MapSet struct { Description string SurfaceCount int LeftCount int RightCount int CenterCount int // TODO: is there any more structure than this? Should I preserve empty lines? SurfacePalette []string LeftPalette []string RightPalette []string CenterPalette []string } func LoadSets(dir string) (map[string]*MapSet, error) { fis, err := ioutil.ReadDir(dir) if err != nil { return nil, err } out := make(map[string]*MapSet, len(fis)) for _, fi := range fis { filename := filepath.Join(dir, fi.Name()) basename := filepath.Base(filename) extname := filepath.Ext(filename) // Don't try to load non-.obj files if !strings.EqualFold(extname, ".set") { continue } obj, err := LoadSet(filename) if err != nil { return nil, fmt.Errorf("%s: %v", filename, err) } out[basename] = obj } return out, nil } func LoadSet(filename string) (*MapSet, error) { out := &MapSet{} s, err := asciiscan.New(filename) if err != nil { return nil, err } defer s.Close() out.Description, err = s.ConsumeString() if err != nil { return nil, err } if err := consumeDefs(s, out); err != nil { return nil, err } if err := consumePalette(s, out.SurfaceCount, &out.SurfacePalette); err != nil { return nil, fmt.Errorf("Failed to read surface palette: %v", err) } if err := consumePalette(s, out.LeftCount, &out.LeftPalette); err != nil { return nil, fmt.Errorf("Failed to read left palette: %v", err) } if err := consumePalette(s, out.RightCount, &out.RightPalette); err != nil { return nil, fmt.Errorf("Failed to read right palette: %v", err) } if err := consumePalette(s, out.CenterCount, &out.CenterPalette); err != nil { return nil, fmt.Errorf("Failed to read center palette: %v", err) } return out, nil } func consumeDefs(scanner *asciiscan.Scanner, in *MapSet) error { expectDefs, err := scanner.ConsumeString() if err != nil { return err } if expectDefs != "Defs" { return fmt.Errorf("Couldn't find Defs section") } defs, err := scanner.ConsumeString() if err != nil { return err } parts := strings.SplitN(defs, " ", -1) if len(parts) != 4 { return fmt.Errorf("Defs section did not have 4 components") } ints := make([]int, 4) for i, part := range parts { n, err := strconv.ParseInt(part, 10, 8) if err != nil { return err } ints[i] = int(n) // safe as we specify 8 bits to ParseInt } in.SurfaceCount = ints[0] in.LeftCount = ints[1] in.RightCount = ints[2] in.CenterCount = ints[3] return nil } func consumePalette(scanner *asciiscan.Scanner, n int, in *[]string) error { out := make([]string, 0, n) for i := 0; i < n; i++ { str, err := scanner.ConsumeString() if err != nil { return err // EOF is bad: the number of entries is explicit } out = append(out, str) } *in = out return nil }