func (t Transfer) generate(name string, r *byteio.StickyReader, w *byteio.StickyWriter, f *os.File, size int64) error { gp.Add(1) defer gp.Done() mp := t.c.NewMap() if mp == nil { return errors.New("failed to create map") } done := false defer func() { if !done { t.c.RemoveMap(mp.ID) } t.c.Save() }() mp.Lock() mp.Name = name mapPath := mp.Path mp.Server = -2 mp.Unlock() t.c.Generators.mu.RLock() gs := make([]data.Generator, len(t.c.Generators.List)) for n, g := range t.c.Generators.List { gs[n] = *g } t.c.Generators.mu.RUnlock() var g data.Generator if len(gs) == 0 { return errors.New("no generators installed") } else if len(gs) == 1 { g = gs[0] } else { w.WriteUint8(1) w.WriteInt16(int16(len(gs))) for _, tg := range gs { data.WriteString(w, tg.Name) } if w.Err != nil { return w.Err } gID := r.ReadInt16() if r.Err != nil { return r.Err } if gID < 0 || int(gID) >= len(gs) { return errors.New("unknown generator") } g = gs[gID] } ms := DefaultMapSettings() ms["level-type"] = minecraft.FlatGenerator ms["generator-settings"] = "0" ms["motd"] = name j, err := os.Open(path.Join(g.Path, "data.gen")) if err != nil { return err } var gj data.GeneratorData err = json.NewDecoder(j).Decode(&gj) j.Close() if err != nil { return err } for k, v := range gj.Options { ms[k] = v } pf, err := os.Create(path.Join(mapPath, "properties.map")) if err != nil { return err } if err = ms.WriteTo(pf); err != nil { return err } pf.Close() cmd := exec.Command(t.c.Settings().GeneratorExecutable) cmd.ExtraFiles = append(cmd.ExtraFiles, f) cmd.Dir, err = os.Getwd() if err != nil { return err } cmd.Stdout = w pw, err := cmd.StdinPipe() if err != nil { return err } err = gp.Start(cmd) if err != nil { return err } defer gp.Remove(cmd) pww := byteio.StickyWriter{Writer: &byteio.LittleEndianWriter{pw}} pww.WriteUint64(t.c.Settings().GeneratorMaxMem) pww.WriteInt64(size) data.WriteString(&pww, g.Path) data.WriteString(&pww, name) data.WriteString(&pww, mapPath) if pww.Err != nil { return pww.Err } err = cmd.Wait() if err != nil { return err } done = true mp.Lock() mp.Server = -1 mp.Unlock() return nil }