func transferFile(typeName, method string, typeID uint8, o *overlay.Overlay) dom.Node { name := xform.InputText("name", "") url := xform.InputRadio("url", "switch", true) upload := xform.InputRadio("upload", "switch", false) fileI := xform.InputUpload("") urlI := xform.InputURL("", "") s := xform.InputSubmit(method) name.Required = true typeFunc := func(dom.Event) { if url.Checked { urlI.Style().RemoveProperty("display") fileI.Style().SetProperty("display", "none", "") urlI.Required = true fileI.Required = false fileI.SetID("") urlI.SetID("file") } else { fileI.Style().RemoveProperty("display") urlI.Style().SetProperty("display", "none", "") fileI.Required = true urlI.Required = false urlI.SetID("") fileI.SetID("file") } } typeFunc(nil) url.AddEventListener("change", false, typeFunc) upload.AddEventListener("change", false, typeFunc) f := xjs.AppendChildren(xdom.Form(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), method+" "+typeName), xform.Label(typeName+" Name", "name"), name, xdom.Br(), xform.Label("URL", "url"), url, xdom.Br(), xform.Label("Upload", "upload"), upload, xdom.Br(), xform.Label("File", "file"), fileI, urlI, xdom.Br(), s, )) s.AddEventListener("click", false, func(e dom.Event) { if name.Value == "" { return } if url.Checked { if urlI.Value == "" { return } } else if len(fileI.Files()) != 1 { return } s.Disabled = true name.Disabled = true url.Disabled = true upload.Disabled = true fileI.Disabled = true urlI.Disabled = true e.PreventDefault() go func() { d := xdom.Div() uo := overlay.New(d) uo.OnClose(func() { o.Close() }) xjs.Body().AppendChild(uo) status := xdom.Div() d.AppendChild(xjs.SetInnerText(status, "Transferring...")) conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/transfer") if err != nil { xjs.SetInnerText(status, err.Error()) return } defer conn.Close() w := byteio.StickyWriter{Writer: byteio.LittleEndianWriter{Writer: conn}} r := byteio.StickyReader{Reader: byteio.LittleEndianReader{Reader: conn}} pb := progress.New(color.RGBA{255, 0, 0, 0}, color.RGBA{0, 0, 255, 0}, 400, 50) d.AppendChild(pb) if url.Checked { w.WriteUint8(typeID << 1) data.WriteString(&w, urlI.Value) length := int(r.ReadInt32()) total := 0 for total < length { switch v := r.ReadUint8(); v { case 1: i := int(r.ReadInt32()) total += i pb.Percent(100 * total / length) default: xjs.SetInnerText(status, ReadError(&r).Error()) return } } } else { f := files.NewFileReader(files.NewFile(fileI.Files()[0])) l := f.Len() if l == 0 { xjs.SetInnerText(status, "Zero-length file") return } w.WriteUint8(typeID<<1 | 1) w.WriteInt32(int32(l)) io.Copy(&w, pb.Reader(f, l)) } d.RemoveChild(pb) xjs.SetInnerText(status, "Checking File") data.WriteString(&w, name.Value) var ctx *dom.CanvasRenderingContext2D for { switch v := r.ReadUint8(); v { case 0: if r.Err != nil { xjs.SetInnerText(status, r.Err.Error()) } else { xjs.SetInnerText(status, ReadError(&r).Error()) } return case 1: files := make([]xform.Option, r.ReadInt16()) for i := range files { files[i] = xform.Option{ Value: strconv.Itoa(i), Label: data.ReadString(&r), } } j := xform.SelectBox("files", files...) sel := xjs.SetInnerText(xdom.Button(), "Select") fo := overlay.New(xjs.AppendChildren(xdom.Div(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), "Please select the "+typeName+" file"), xform.Label("File", "files"), j, xdom.Br(), sel, ))) c := make(chan int16, 0) done := false fo.OnClose(func() { if !done { done = true c <- -1 } }) sel.AddEventListener("click", false, func(dom.Event) { if !done { done = true v, err := strconv.Atoi(j.Value) if err != nil { v = -1 } c <- int16(v) fo.Close() } }) xjs.Body().AppendChild(fo) w.WriteInt16(<-c) close(c) case 2: w := r.ReadInt32() h := r.ReadInt32() canvas := xdom.Canvas() canvas.Width = int(w) * 8 canvas.Height = int(h) * 8 d.AppendChild(canvas) ctx = canvas.GetContext2d() ctx.Scale(8, 8) case 3: xjs.SetInnerText(status, data.ReadString(&r)) case 4: x := r.ReadInt32() y := r.ReadInt32() red := r.ReadUint8() green := r.ReadUint8() blue := r.ReadUint8() alpha := r.ReadUint8() ctx.FillStyle = "rgba(" + strconv.Itoa(int(red)) + ", " + strconv.Itoa(int(green)) + ", " + strconv.Itoa(int(blue)) + ", " + strconv.FormatFloat(float64(alpha)/255, 'f', -1, 32) + ")" ctx.FillRect(int(x), int(y), 1, 1) case 255: uo.Close() return } } }() }) return f }
func generate(r *byteio.StickyReader, w *byteio.StickyWriter, of *os.File) error { memoryLimit := r.ReadUint64() size := r.ReadInt64() gPath := data.ReadString(r) levelName := data.ReadString(r) mapPath := data.ReadString(r) if r.Err != nil { return r.Err } o, err := ora.Open(of, size) if err != nil { return err } f, err := os.Open(path.Join(gPath, "data.gen")) if err != nil { return err } g, err := LoadGenerator(f) if e := f.Close(); e != nil { return e } if err != nil { return err } b := o.Bounds() w.WriteUint8(2) w.WriteInt32(int32(b.Max.X) >> 4) w.WriteInt32(int32(b.Max.Y) >> 4) c := make(chan paint, 1024) m := make(chan string, 4) e := make(chan struct{}, 0) go func() { defer close(e) defer close(m) defer close(c) for { select { case message := <-m: w.WriteUint8(3) data.WriteString(w, message) case p := <-c: w.WriteUint8(4) w.WriteInt32(p.X) w.WriteInt32(p.Y) r, g, b, a := p.RGBA() w.WriteUint8(uint8(r >> 8)) w.WriteUint8(uint8(g >> 8)) w.WriteUint8(uint8(b >> 8)) w.WriteUint8(uint8(a >> 8)) case <-e: return } } }() err = g.Generate(levelName, mapPath, o, c, m, memoryLimit) e <- struct{}{} <-e return err }
func serverConsole(s data.Server) func(dom.Element) { return func(c dom.Element) { log := xform.TextArea("log", "") log.ReadOnly = true command := xform.InputText("command", "") command.Required = true send := xform.InputSubmit("Send") c.AppendChild(xjs.AppendChildren(xdom.Form(), xjs.AppendChildren(xdom.Fieldset(), xjs.SetInnerText(xdom.Legend(), "Console"), xform.Label("Log", ""), log, xdom.Br(), xform.Label("Command", "command"), command, send, ))) if s.State == data.StateStopped { send.Disabled = true command.Disabled = true } else { send.AddEventListener("click", false, func(e dom.Event) { if command.Value == "" { return } e.PreventDefault() send.Disabled = true cmd := command.Value log.Value += "\n>" + cmd + "\n" log.Set("scrollTop", log.Get("scrollHeight")) command.Value = "" go func() { err := RPC.WriteCommand(s.ID, cmd) if err != nil { xjs.Alert("Error sending command: %s", err) return } send.Disabled = false }() }) } go func() { conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/console") if err != nil { xjs.Alert("Failed to connect to console: %s", err) return } defer conn.Close() w := byteio.StickyWriter{Writer: byteio.LittleEndianWriter{Writer: conn}} r := byteio.StickyReader{Reader: byteio.LittleEndianReader{Reader: conn}} updateStop := make(chan struct{}) registerUpdateStopper(c, updateStop) done := false go func() { <-updateStop done = true conn.Close() }() w.WriteInt32(int32(s.ID)) for { state := r.ReadUint8() switch state { case 0: if !done { err := ReadError(&r) if r.Err != nil { err = r.Err } log.Value += "\n\nError reading from console: " + err.Error() log.Set("scrollTop", log.Get("scrollHeight")) } return case 1: log.Value += data.ReadString(&r) log.Set("scrollTop", log.Get("scrollHeight")) } } }() } }