diff --git a/frontend/src/pages/Server.tsx b/frontend/src/pages/Server.tsx index 88d4fb2..36e84aa 100644 --- a/frontend/src/pages/Server.tsx +++ b/frontend/src/pages/Server.tsx @@ -12,7 +12,7 @@ import { TabList, Tabs, Tooltip } from "@mui/joy"; -import {Settings} from "./server/Settings"; +import {Administration} from "./server/Administration"; import {General} from "./server/General"; import {useEffect, useState} from "react"; import {server} from "../../wailsjs/go/models"; @@ -27,6 +27,7 @@ import {InstallUpdater} from "./InstallUpdater"; import {useAlert} from "../components/AlertProvider"; import {BrowserOpenURL, EventsOff, EventsOn} from "../../wailsjs/runtime"; import {IconAlertCircleFilled, IconExternalLink} from "@tabler/icons-react"; +import {Console} from "./server/Console"; type Props = { @@ -73,6 +74,13 @@ export const Server = ({id, className}: Props) => { EventsOn("onServerExit", () => setServerStatus(false)) return () => EventsOff("onServerExit") }, []); + + useEffect(() => { + if (serv.id >= 0) { + refreshServerStatus() + } + }, [serv]); + //endregion function onServerStartButtonClicked() { @@ -137,14 +145,13 @@ export const Server = ({id, className}: Props) => { + Console General - Settings - Mods - Plugins - Modifiers + Administration + - + ) : ( setIsInstalled(true)}/>)} ); diff --git a/frontend/src/pages/server/Administration.tsx b/frontend/src/pages/server/Administration.tsx new file mode 100644 index 0000000..9e014d4 --- /dev/null +++ b/frontend/src/pages/server/Administration.tsx @@ -0,0 +1,9 @@ +import {TabPanel} from "@mui/joy"; + +export function Administration() { + return ( + + + + ); +} \ No newline at end of file diff --git a/frontend/src/pages/server/Console.tsx b/frontend/src/pages/server/Console.tsx new file mode 100644 index 0000000..1ff5027 --- /dev/null +++ b/frontend/src/pages/server/Console.tsx @@ -0,0 +1,98 @@ +import { Button, Input, TabPanel } from "@mui/joy"; +import React, { useEffect, useRef, useState } from "react"; +import { server } from "../../../wailsjs/go/models"; +import { SendRconCommand } from "../../../wailsjs/go/helpers/HelpersController"; + +type Message = { + text: string; + sender: string; +}; + +type Props = { + setServ: React.Dispatch>; + serv: server.Server; + serverStatus: boolean; +}; + +export function Console({ setServ, serv, serverStatus }: Props) { + const [input, setInput] = useState(""); + const [messages, setMessages] = useState([]); + + const terminalRef = useRef(null); + + const writeToConsole = (text: string, sender: string = "user") => { + const newMessage: Message = { text, sender }; + setMessages((prevMessages) => [...prevMessages, newMessage]); + }; + + const doRconCommand = (text: string) => { + SendRconCommand(text, serv.ipAddress, serv.rconPort, serv.adminPassword) + .then((resp) => writeToConsole(resp, "server")) + .catch((err) => writeToConsole("error sending command: " + err, "server")); + }; + + useEffect(() => { + if (terminalRef.current) { + terminalRef.current.scrollTop = terminalRef.current.scrollHeight; + } + }, [messages]); + + if (serverStatus) { + return ( + +
+ {messages.map((message, index) => ( +
+ {message.sender === "server" ? ( + {message.text}
+ ) : ( + + [{message.sender}]{" "} + $ {message.text}
+
+ )} +
+ ))} +
+ setInput(e.target.value)} + startDecorator={$} + endDecorator={ + + } + onKeyPress={(e) => { + if (e.key === "Enter") { + writeToConsole(input, "user"); + doRconCommand(input); + setInput(""); + } + }} + > +
+ ); + } else { + return ( + +
+

Server is not running

+
+
+ ); + } +} diff --git a/frontend/src/pages/server/General.tsx b/frontend/src/pages/server/General.tsx index 7e41562..7a4e045 100644 --- a/frontend/src/pages/server/General.tsx +++ b/frontend/src/pages/server/General.tsx @@ -42,7 +42,7 @@ export function General({serv, setServ}: Props) { }, []); return ( - + {/* Server Name and Passwords */} @@ -80,7 +80,7 @@ export function General({serv, setServ}: Props) { IP Address: Ports: diff --git a/frontend/src/pages/server/Settings.tsx b/frontend/src/pages/server/Settings.tsx deleted file mode 100644 index d254c94..0000000 --- a/frontend/src/pages/server/Settings.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import {TabPanel} from "@mui/joy"; - -export function Settings() { - return ( - - - - ); -} \ No newline at end of file diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs index 75fd2b7..d1b9227 100644 --- a/frontend/tailwind.config.cjs +++ b/frontend/tailwind.config.cjs @@ -4,7 +4,11 @@ module.exports = { "./src/**/*.{js,jsx,ts,tsx}", ], theme: { - extend: {}, + extend: { + fontFamily: { + 'jetbrains': ['JetBrains Mono', 'monospace'], + }, + }, }, plugins: [], diff --git a/go.mod b/go.mod index da94d64..ba02ec5 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.18 require ( github.com/adrg/xdg v0.4.0 + github.com/gorcon/rcon v1.3.4 github.com/jensvandewiel/gosteamcmd v0.1.2 github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/sethvargo/go-password v0.2.0 diff --git a/go.sum b/go.sum index b4ee6bf..8450af4 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,8 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorcon/rcon v1.3.4 h1:TExNhWI2mJlqpCg49vajUgznvEZbEzQWKujY1Sy+/AY= +github.com/gorcon/rcon v1.3.4/go.mod h1:46+oSXgPwlRAkcAPStkNnIL1dlcxJweKVNWshy3hDJI= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jensvandewiel/gosteamcmd v0.1.2 h1:NHichoj0v3GvSVN2Fn36dSOLosHAytpaKnLnDHTMQPI= diff --git a/helpers/rcon.go b/helpers/rcon.go new file mode 100644 index 0000000..25ba707 --- /dev/null +++ b/helpers/rcon.go @@ -0,0 +1,22 @@ +package helpers + +import ( + "fmt" + "github.com/gorcon/rcon" + "strconv" +) + +func (c *HelpersController) SendRconCommand(command string, ip string, port int, password string) (string, error) { + conn, err := rcon.Dial(ip+":"+strconv.Itoa(port), password) + if err != nil { + return "", fmt.Errorf("failed connectting to rcon server: %v", err) + } + defer conn.Close() + + response, err := conn.Execute(command) + if err != nil { + return "", fmt.Errorf("failed executing rcon command: %v", err) + } + + return response, nil +} diff --git a/server/helpers.go b/server/helpers.go index 0383fa0..94b4539 100644 --- a/server/helpers.go +++ b/server/helpers.go @@ -84,7 +84,9 @@ func CheckIfServerCorrect(server Server) error { return fmt.Errorf("Checks failed: Server.AdminPassword is too short.") } - if server.IpAddress != "0.0.0.0" { + if server.IpAddress == "" { + return fmt.Errorf("Check failed: Ip address is empty") + } else { interfaces, err := helpers.GetNetworkInterfaces() if err != nil { @@ -109,6 +111,12 @@ func CheckIfServerCorrect(server Server) error { } } + if server.ServerMap == "" { + return fmt.Errorf("server.serverMap is empty") + } else if server.ServerMap != "TheIsland_WP" { + return fmt.Errorf("server.serverMap has invalid value: %v", server.ServerMap) + } + return nil } diff --git a/server/server.go b/server/server.go index 1edf473..859d98e 100644 --- a/server/server.go +++ b/server/server.go @@ -74,6 +74,7 @@ func (s *Server) Start() error { if err != nil { return fmt.Errorf("error starting server: %v", err) } + runtime.EventsEmit(s.ctx, "onServerStart", s.Id) go func() { _ = s.Command.Wait()