Skip to content

Commit

Permalink
get started with http gui
Browse files Browse the repository at this point in the history
  • Loading branch information
oq-x committed Sep 8, 2023
1 parent ce08c51 commit 9e27750
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 115 deletions.
6 changes: 6 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ func defaultConfig() server.ServerConfig {
ServerClosed: "Server closed.",
OnlineMode: "The server is in online mode.",
},
GUI: server.GUI{
ServerIP: "0.0.0.0",
ServerPort: 8080,
Password: "ChangeMe",
Enable: false,
},
Tablist: server.Tablist{
Header: []string{},
Footer: []string{},
Expand Down
112 changes: 25 additions & 87 deletions gui/gui.go
Original file line number Diff line number Diff line change
@@ -1,104 +1,42 @@
package gui

import (
"fmt"
"io"
"net/http"
"strconv"
"strings"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"github.com/dynamitemc/dynamite/util"
)

var playerCountText *widget.RichText
var playerContainer *widget.List
var consoleText []string
var console *widget.TextGrid
var players = map[int][2]string{}
var indexes = map[string]int{}
var maxPlayers string

func AddPlayer(name string, uuid string) {
indexes[uuid] = len(players)
players[len(players)] = [2]string{uuid, name}
if playerCountText != nil {
playerCountText.ParseMarkdown(fmt.Sprintf("### %d/%s players", len(players), maxPlayers))
}
if playerContainer != nil {
playerContainer.Refresh()
}
type logger interface {
Error(string, ...interface{})
Info(string, ...interface{})
Debug(string, ...interface{})
}

func RemovePlayer(uuid string) {
delete(players, indexes[uuid])
if playerCountText != nil {
playerCountText.ParseMarkdown(fmt.Sprintf("### %d/%s players", len(players), maxPlayers))
}
if playerContainer != nil {
playerContainer.Refresh()
}
}
var log logger

func SetMaxPlayers(max int) {
if max == -1 {
maxPlayers = "Unlimited"
}
maxPlayers = strconv.Itoa(max)
if playerCountText != nil {
playerCountText.ParseMarkdown(fmt.Sprintf("### %d/%s players", len(players), maxPlayers))
}
}
type handler struct{}

func Log(str string) {
consoleText = append(consoleText, str)
if console != nil {
console.SetText(strings.Join(consoleText, "\n"))
func (handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var code int
switch r.RequestURI {
case "/":
{
io.WriteString(w, "hello there!")
}
}
log.Debug("[GUI] [%s] visited %s | Code %d", r.RemoteAddr, r.RequestURI, code)
}

func LaunchGUI() {
app := app.New()
window := app.NewWindow("Dynamite Server")
title := widget.NewRichTextFromMarkdown("# Dynamite Server")
consoleTitle := widget.NewRichTextFromMarkdown("## Console")
console = widget.NewTextGridFromString(strings.Join(consoleText, "\n"))
command := widget.NewEntry()
command.SetPlaceHolder("Input a command")
command.OnSubmitted = func(s string) {
//server.Command("console", s)
command.SetText("")
func LaunchGUI(addr string, password string, l logger) {
log = l
if len(password) < 8 && !util.HasArg("-no_password_req") {
log.Error("Failed to start http gui panel. Password must be at least 8 characters long. You can bypass this using -no_password_req")
return
}
log.Info("Launching http gui panel at http://%s", addr)
err := http.ListenAndServe(addr, handler{})
if err != nil {
log.Error("Failed to start http gui panel: %s", err)
}
console := container.NewBorder(consoleTitle, command, nil, nil, container.NewScroll(console))

playersTitle := widget.NewRichTextFromMarkdown("## Players")
playerCountText = widget.NewRichTextFromMarkdown(fmt.Sprintf("### %s/%s players", "0", maxPlayers))
playerContainer = widget.NewList(
func() int {
return len(players)
},
func() fyne.CanvasObject {
return container.NewHBox()
},
func(i widget.ListItemID, o fyne.CanvasObject) {
cont := o.(*fyne.Container)
if len(cont.Objects) == 0 {
player := players[i]
res, _ := http.Get(fmt.Sprintf("https://crafatar.com/avatars/%s", player[0]))
skinData, _ := io.ReadAll(res.Body)
skin := widget.NewIcon(fyne.NewStaticResource("skin", skinData))
skin.Resize(fyne.NewSize(640, 640))
cont.Objects = append(cont.Objects, skin, widget.NewRichTextFromMarkdown("### "+player[1]))
cont.Refresh()
}
})
players := container.NewBorder(container.NewVBox(playersTitle, playerCountText), nil, nil, nil, playerContainer)
sp := container.NewHSplit(console, players)
sp.SetOffset(0.6)
window.SetContent(container.NewBorder(title, nil, nil, nil, sp))
window.Resize(fyne.NewSize(700, 300))

window.ShowAndRun()
}
104 changes: 104 additions & 0 deletions gui/legacygui.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package gui

import (
"fmt"
"io"
"net/http"
"strconv"
"strings"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)

var playerCountText *widget.RichText
var playerContainer *widget.List
var consoleText []string
var console *widget.TextGrid
var players = map[int][2]string{}
var indexes = map[string]int{}
var maxPlayers string

func AddPlayer(name string, uuid string) {
indexes[uuid] = len(players)
players[len(players)] = [2]string{uuid, name}
if playerCountText != nil {
playerCountText.ParseMarkdown(fmt.Sprintf("### %d/%s players", len(players), maxPlayers))
}
if playerContainer != nil {
playerContainer.Refresh()
}
}

func RemovePlayer(uuid string) {
delete(players, indexes[uuid])
if playerCountText != nil {
playerCountText.ParseMarkdown(fmt.Sprintf("### %d/%s players", len(players), maxPlayers))
}
if playerContainer != nil {
playerContainer.Refresh()
}
}

func SetMaxPlayers(max int) {
if max == -1 {
maxPlayers = "Unlimited"
}
maxPlayers = strconv.Itoa(max)
if playerCountText != nil {
playerCountText.ParseMarkdown(fmt.Sprintf("### %d/%s players", len(players), maxPlayers))
}
}

func Log(str string) {
consoleText = append(consoleText, str)
if console != nil {
console.SetText(strings.Join(consoleText, "\n"))
}
}

func LaunchLegacyGUI() {
app := app.New()
window := app.NewWindow("Dynamite Server")
title := widget.NewRichTextFromMarkdown("# Dynamite Server")
consoleTitle := widget.NewRichTextFromMarkdown("## Console")
console = widget.NewTextGridFromString(strings.Join(consoleText, "\n"))
command := widget.NewEntry()
command.SetPlaceHolder("Input a command")
command.OnSubmitted = func(s string) {
//server.Command("console", s)
command.SetText("")
}
console := container.NewBorder(consoleTitle, command, nil, nil, container.NewScroll(console))

playersTitle := widget.NewRichTextFromMarkdown("## Players")
playerCountText = widget.NewRichTextFromMarkdown(fmt.Sprintf("### %s/%s players", "0", maxPlayers))
playerContainer = widget.NewList(
func() int {
return len(players)
},
func() fyne.CanvasObject {
return container.NewHBox()
},
func(i widget.ListItemID, o fyne.CanvasObject) {
cont := o.(*fyne.Container)
if len(cont.Objects) == 0 {
player := players[i]
res, _ := http.Get(fmt.Sprintf("https://crafatar.com/avatars/%s", player[0]))
skinData, _ := io.ReadAll(res.Body)
skin := widget.NewIcon(fyne.NewStaticResource("skin", skinData))
skin.Resize(fyne.NewSize(640, 640))
cont.Objects = append(cont.Objects, skin, widget.NewRichTextFromMarkdown("### "+player[1]))
cont.Refresh()
}
})
players := container.NewBorder(container.NewVBox(playersTitle, playerCountText), nil, nil, nil, playerContainer)
sp := container.NewHSplit(console, players)
sp.SetOffset(0.6)
window.SetContent(container.NewBorder(title, nil, nil, nil, sp))
window.Resize(fyne.NewSize(700, 300))

window.ShowAndRun()
}
13 changes: 2 additions & 11 deletions logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,13 @@ package logger

import (
"fmt"
"os"
"time"

"github.com/dynamitemc/dynamite/gui"
"github.com/dynamitemc/dynamite/util"
"github.com/fatih/color"
)

func HasArg(arg string) bool {
for _, s := range os.Args {
if s == arg {
return true
}
}
return false
}

type Logger struct {
FilePath string
ConsoleText []string
Expand Down Expand Up @@ -47,7 +38,7 @@ func (logger *Logger) Print(format string, a ...interface{}) {
}

func (logger *Logger) Debug(format string, a ...interface{}) {
if !HasArg("-debug") {
if !util.HasArg("-debug") {
return
}
cyan := color.New(color.FgCyan).Add(color.Bold).SprintFunc()
Expand Down
22 changes: 18 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"os"
"strconv"
"time"
Expand All @@ -9,6 +10,7 @@ import (
"github.com/dynamitemc/dynamite/gui"
"github.com/dynamitemc/dynamite/logger"
"github.com/dynamitemc/dynamite/server"
"github.com/dynamitemc/dynamite/util"
)

var log logger.Logger
Expand All @@ -34,10 +36,22 @@ func main() {
var cfg server.ServerConfig
config.LoadConfig("config.toml", &cfg)
log.Debug("Loaded config")
if !logger.HasArg("-nogui") {
go start(cfg)
log.Info("Loading GUI panel")
gui.LaunchGUI()
if cfg.GUI.Enable {
if !util.HasArg("-nogui") {
go gui.LaunchGUI(fmt.Sprintf("%s:%d", cfg.GUI.ServerIP, cfg.GUI.ServerPort), cfg.GUI.Password, &log)
} else {
log.Warn("Remove the -nogui argument to load the gui panel")
}
}
if util.HasArg("-uselegacygui") {
if !util.HasArg("-nogui") {
go start(cfg)
log.Info("Loading legacy GUI panel")
gui.LaunchLegacyGUI()
} else {
log.Warn("Remove the -nogui argument to load the legacy gui panel")
start(cfg)
}
} else {
start(cfg)
}
Expand Down
23 changes: 10 additions & 13 deletions server/server_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@ package server

import (
"os"
"strings"
"sync"

"github.com/aimjel/minecraft"
"github.com/dynamitemc/dynamite/gui"
"github.com/dynamitemc/dynamite/logger"
"github.com/dynamitemc/dynamite/server/player"
"github.com/dynamitemc/dynamite/server/world"
"github.com/dynamitemc/dynamite/util"
)

type Tablist struct {
Header []string `toml:"header"`
Footer []string `toml:"footer"`
}

type GUI struct {
ServerIP string `toml:"server_ip"`
ServerPort int `toml:"server_port"`
Password string `toml:"password"`
Enable bool `toml:"enable"`
}

type Messages struct {
NotInWhitelist string `toml:"not_in_whitelist"`
Banned string `toml:"banned"`
Expand Down Expand Up @@ -51,6 +58,7 @@ type ServerConfig struct {
SimulationDistance int `toml:"simulation_distance"`
MOTD string `toml:"motd"`
Whitelist Whitelist `toml:"whitelist"`
GUI GUI `toml:"gui"`
Gamemode string `toml:"gamemode"`
Hardcore bool `toml:"hardcore"`
MaxPlayers int `toml:"max_players"`
Expand All @@ -60,17 +68,6 @@ type ServerConfig struct {
Messages Messages `toml:"messages"`
}

func GetWorldPath() string {
for _, arg := range os.Args {
if strings.HasPrefix(arg, "worldpath=") {
if strings.TrimPrefix(arg, "worldpath=") != "" {
return strings.TrimPrefix(arg, "worldpath=")
}
}
}
return "world"
}

func (cfg *ServerConfig) Listen(address string, logger logger.Logger) (*Server, error) {
lnCfg := minecraft.ListenConfig{
Status: minecraft.NewStatus(minecraft.Version{
Expand All @@ -91,7 +88,7 @@ func (cfg *ServerConfig) Listen(address string, logger logger.Logger) (*Server,
if err != nil {
return nil, err
}
w, err := world.OpenWorld(GetWorldPath())
w, err := world.OpenWorld(util.GetArg("worldpath", "world"))
if err != nil {
logger.Error("Failed to load world: %s", err)
os.Exit(1)
Expand Down
Loading

0 comments on commit 9e27750

Please sign in to comment.