func main() { dom.GetWindow().AddEventListener("load", false, func(dom.Event) { go func() { if err := rpcInit(); err != nil { xjs.Alert("Failed to connect to RPC server: %s", err) return } title, err := RPC.ServerName() if err != nil { xjs.Alert("Error retrieving server name: %s", err) return } body := dom.GetWindow().Document().(dom.HTMLDocument).Body() body.Underlying().Set("spellcheck", "false") xjs.RemoveChildren(body) body.AppendChild(xdom.H1()) SetTitle(title) body.AppendChild(tabs.New([]tabs.Tab{ {"Servers", ServersTab()}, {"Maps", MapsTab()}, {"Generators", GeneratorsTab}, {"Settings", settingsTab}, })) }() }) }
func GeneratorsTab(c dom.Element) { go func() { xjs.RemoveChildren(c) gs, err := RPC.Generators() if err != nil { xjs.Alert("Error getting generator list: %s", err) return } ng := xdom.Button() xjs.SetInnerText(ng, "New Generator") ng.AddEventListener("click", false, func(dom.Event) { d := xdom.Div() o := overlay.New(d) o.OnClose(func() { GeneratorsTab(c) }) d.AppendChild(transferFile("Map", "Upload/Download", 3, o)) xjs.Body().AppendChild(o) }) table := xjs.AppendChildren(xdom.Table(), xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(xdom.Th(), "Generator"))) if len(gs) == 0 { table.AppendChild(xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(xdom.Td(), "No Generators"))) } else { for _, g := range gs { td := xdom.Td() td.AddEventListener("click", false, func(g data.Generator) func(dom.Event) { return func(dom.Event) { d := xdom.Div() o := overlay.New(d) o.OnClose(func() { GeneratorsTab(c) }) d.AppendChild(tabs.New([]tabs.Tab{ {"Profile", generatorProfile(g.ID)}, {"Misc", misc("generator", g.ID, o, RPC.RemoveGenerator)}, })) xjs.Body().AppendChild(o) } }(g)) table.AppendChild(xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(td, g.Name))) } } xjs.AppendChildren(c, xjs.SetInnerText(xdom.H2(), "Generators"), ng, table, ) }() }
func MapsTab() func(dom.Element) { forceUpdate := make(chan struct{}) nm := xdom.Button() nm.AddEventListener("click", false, func(dom.Event) { d := xdom.Div() o := overlay.New(d) o.OnClose(func() { go func() { forceUpdate <- struct{}{} }() }) xjs.AppendChildren(d, xjs.SetInnerText(xdom.H1(), "New Map"), tabs.New([]tabs.Tab{ {"Create", createMap(o)}, {"Upload/Download", func(c dom.Element) { c.AppendChild(transferFile("Map", "Upload/Download", 1, o)) }}, {"Generate", func(c dom.Element) { c.AppendChild(transferFile("Map", "Generate", 2, o)) }}, }), ) xjs.Body().AppendChild(o) }) noneTd := xdom.Td() noneTd.ColSpan = 2 none := xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(noneTd, "No Maps Found")) mapList := xjs.AppendChildren(xdom.Table(), xjs.AppendChildren(xdom.Thead(), xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(xdom.Th(), "Map Name"), xjs.SetInnerText(xdom.Th(), "Status"), )), none, ) nodes := xjs.AppendChildren(xdom.Div(), xjs.SetInnerText(xdom.H2(), "Maps"), xjs.SetInnerText(nm, "New Map"), mapList, ) maps := make(map[int]*Map) return func(c dom.Element) { c.AppendChild(nodes) updateStop := make(chan struct{}) registerUpdateStopper(c, updateStop) for { mps, err := RPC.MapList() if err != nil { xjs.Alert("Error getting map list: %s", err) return } if none.ParentNode() != nil { mapList.RemoveChild(none) } for _, m := range maps { m.ID = -1 } for _, m := range mps { om, ok := maps[m.ID] if ok { om.Map = m } else { name := xdom.Td() status := xdom.Td() om = &Map{ Map: m, row: xjs.AppendChildren(xdom.Tr(), name, status, ), name: name, status: status, } maps[m.ID] = om mapList.AppendChild(om.row) name.Class().SetString("mapName") name.AddEventListener("click", false, func() func(dom.Event) { m := om return func(dom.Event) { div := xdom.Div() o := overlay.New(div) div.AppendChild(tabs.New([]tabs.Tab{ {"General", mapGeneral(m.Map)}, {"Properties", mapProperties(m.Map)}, {"Misc.", misc("map", m.Map.ID, o, RPC.RemoveMap)}, })) o.OnClose(func() { go func() { forceUpdate <- struct{}{} }() }) xjs.Body().AppendChild(o) } }()) } switch om.Server { case -2: xjs.SetInnerText(om.status, "Busy") om.status.Style().SetProperty("color", "#f00", "") case -1: xjs.SetInnerText(om.status, "Unassigned") om.status.Style().SetProperty("color", "#00f", "") default: serv, err := RPC.Server(om.Server) if err == nil { xjs.SetInnerText(om.status, "Assigned") } else { xjs.SetInnerText(om.status, "Assigned - "+serv.Name) } om.status.Style().SetProperty("color", "#000", "") } xjs.SetInnerText(om.name, om.Name) } for id, m := range maps { if m.ID == -1 { delete(maps, id) mapList.RemoveChild(m.row) } } if len(maps) == 0 { mapList.AppendChild(none) } // Sleep until update if !updateSleep(forceUpdate, updateStop) { return } } } }
func ServersTab() func(dom.Element) { forceUpdate := make(chan struct{}) ns := xdom.Button() ns.AddEventListener("click", false, func(dom.Event) { d := xdom.Div() o := overlay.New(d) d.AppendChild(transferFile("Server", "Upload/Download", 0, o)) o.OnClose(func() { go func() { forceUpdate <- struct{}{} }() }) xjs.Body().AppendChild(o) }) noneTd := xdom.Td() noneTd.ColSpan = 3 none := xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(noneTd, "No Servers Found")) serverList := xjs.AppendChildren(xdom.Table(), xjs.AppendChildren(xdom.Thead(), xjs.AppendChildren(xdom.Tr(), xjs.SetInnerText(xdom.Th(), "Server Name"), xjs.SetInnerText(xdom.Th(), "Status"), xjs.SetInnerText(xdom.Th(), "Controls"), )), none, ) nodes := xjs.AppendChildren(xdom.Div(), xjs.SetInnerText(xdom.H2(), "Servers"), xjs.SetInnerText(ns, "New Server"), serverList, ) servers := make(map[int]*Server) return func(c dom.Element) { c.AppendChild(nodes) updateStop := make(chan struct{}) registerUpdateStopper(c, updateStop) for { servs, err := RPC.ServerList() if err != nil { xjs.Alert("Error getting server list: %s", err) return } if none.ParentNode() != nil { serverList.RemoveChild(none) } for _, s := range servers { s.ID = -1 } for _, s := range servs { os, ok := servers[s.ID] if ok { os.Server = s } else { name := xdom.Td() status := xdom.Td() startStop := xdom.Button() os = &Server{ Server: s, row: xjs.AppendChildren(xdom.Tr(), name, status, xjs.AppendChildren(xdom.Td(), startStop), ), name: name, status: status, button: startStop, } servers[s.ID] = os serverList.AppendChild(os.row) name.Class().SetString("serverName") name.AddEventListener("click", false, func() func(dom.Event) { s := os return func(dom.Event) { go func() { d, err := RPC.ServerEULA(s.ID) if err != nil { d = "" } t := []tabs.Tab{ {"General", serverGeneral(s.Server)}, {"Properties", serverProperties(s.Server)}, {"Console", serverConsole(s.Server)}, } if d != "" { t = append(t, tabs.Tab{"EULA", serverEULA(s.Server, d)}) } div := xdom.Div() o := overlay.New(div) t = append(t, tabs.Tab{"Misc.", misc("server", s.Server.ID, o, RPC.RemoveServer)}) div.AppendChild(tabs.New(t)) o.OnClose(func() { go func() { forceUpdate <- struct{}{} }() }) xjs.Body().AppendChild(o) }() } }()) startStop.AddEventListener("click", false, func() func(dom.Event) { b := startStop s := os return func(dom.Event) { go func() { b.Disabled = true switch s.State { case data.StateStopped: err := RPC.StartServer(s.ID) if err != nil { xjs.Alert("Error starting server: %s", err) return } case data.StateRunning: err := RPC.StopServer(s.ID) if err != nil { xjs.Alert("Error stopping server: %s", err) return } default: return } go func() { forceUpdate <- struct{}{} }() }() } }()) } if os.Map >= 0 { xjs.SetInnerText(os.status, os.State.String()) switch os.State { case data.StateStopped: xjs.SetInnerText(os.button, "Start") os.button.Disabled = false case data.StateRunning: xjs.SetInnerText(os.button, "Stop") os.button.Disabled = false default: xjs.SetInnerText(os.button, "N/A") os.button.Disabled = true } } else { xjs.SetInnerText(os.status, "No Map") os.button.Disabled = true xjs.SetInnerText(os.button, "N/A") } xjs.SetInnerText(os.name, os.Name) } for id, s := range servers { if s.ID == -1 { delete(servers, id) serverList.RemoveChild(s.row) } } if len(servers) == 0 { serverList.AppendChild(none) } // Sleep until update if !updateSleep(forceUpdate, updateStop) { return } } } }
func createMap(o *overlay.Overlay) func(dom.Element) { return func(c dom.Element) { name := xform.InputText("name", "") name.Required = true gmOpts := make([]xform.Option, len(gameModes)) for i, m := range gameModes { gmOpts[i] = xform.Option{ Label: m, Value: strconv.Itoa(i), } } gameMode := xform.SelectBox("gamemode", gmOpts...) seed := xform.InputText("seed", "") structures := xform.InputCheckbox("structures", true) cheats := xform.InputCheckbox("cheats", false) fs := xdom.Fieldset() fs.AppendChild(xjs.SetInnerText(xdom.Legend(), "Create Map")) c.AppendChild(xjs.AppendChildren(xdom.Form(), fs)) dataParser := func(mode int) func() (data.DefaultMap, error) { return func() (data.DefaultMap, error) { data := data.DefaultMap{ Mode: mode, } var err error data.Name = name.Value si := gameMode.SelectedIndex if si < 0 || si >= len(gameModes) { return data, errors.New("invalid gamemode") } if seed.Value == "" { seed.Value = "0" } data.Seed, err = strconv.ParseInt(seed.Value, 10, 64) if err != nil { return data, err } data.Structures = structures.Checked data.Cheats = cheats.Checked return data, nil } } xjs.AppendChildren(fs, xform.Label("Name", "name"), name, xdom.Br(), xform.Label("Game Mode", "gamemode"), gameMode, xdom.Br(), xform.Label("Level Seed", "seed"), seed, xdom.Br(), xform.Label("Structures", "structures"), structures, xdom.Br(), xform.Label("Cheats", "cheats"), cheats, xdom.Br(), tabs.New([]tabs.Tab{ {"Default", createMapMode(0, o, dataParser(0))}, {"Super Flat", createSuperFlatMap(o, dataParser(1))}, {"Large Biomes", createMapMode(2, o, dataParser(2))}, {"Amplified", createMapMode(3, o, dataParser(3))}, {"Customised", createCustomisedMap(o, dataParser(4))}, }), ) } }