Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

#121: Auto-Save #122

Merged
merged 1 commit into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions frontend/src/pages/server/Administration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ function ServerAdministrationCard({setServ, serv, onServerFilesDeleted}: {setSer
</div>
</Card>;
}

function ServerStartupCard({setServ, serv}: {setServ: React.Dispatch<React.SetStateAction<server.Server>>, serv: server.Server}) {

const [showServerCommandModalOpen, setShowServerCommandModalOpen] = useState(false)
Expand Down Expand Up @@ -211,6 +212,38 @@ function ServerStartupCard({setServ, serv}: {setServ: React.Dispatch<React.SetSt
</Card>
)
}

function AutoSaveSettingsCard({ setServ, serv }: {setServ: React.Dispatch<React.SetStateAction<server.Server>>, serv: server.Server}) {
return (
<Card variant="soft" className={''}>
<Typography level="title-md">
Auto-Save Settings
</Typography>
<Divider className={'mx-2'}/>

<div className={'space-x-4 w-full flex'}>
<div className={'inline-block'}>
<Checkbox label="Enable Auto-Save" checked={serv?.autoSaveEnabled}
onChange={(e) => setServ((p) => ({
...p,
autoSaveEnabled: e.target.checked,
convertValues: p.convertValues
}))}/><br/>

<FormLabel>Auto-Save Interval (minutes)</FormLabel>
<Input className={''} type={'number'} required value={serv?.autoSaveInterval} disabled={!serv?.autoSaveEnabled}
onChange={(e) => setServ((p) => ({
...p,
autoSaveInterval: parseInt(e.target.value),
convertValues: p.convertValues
}))}>
</Input>
</div>
</div>
</Card>
)
}

function ExtraSettingsCard({setServ, serv}: {setServ: React.Dispatch<React.SetStateAction<server.Server>>, serv: server.Server}) {
return (
<Card variant="soft" className={''}>
Expand Down Expand Up @@ -257,12 +290,11 @@ function ExtraSettingsCard({setServ, serv}: {setServ: React.Dispatch<React.SetSt
}

export function Administration({setServ, serv, onServerFilesDeleted}: Props) {


return (
<TabPanel value={3} className={'space-y-8'}>
<ServerAdministrationCard serv={serv} setServ={setServ} onServerFilesDeleted={onServerFilesDeleted}/>
<ServerStartupCard serv={serv} setServ={setServ} />
<AutoSaveSettingsCard setServ={setServ} serv={serv}/>
<ExtraSettingsCard setServ={setServ} serv={serv}/>
</TabPanel>
);
Expand Down
21 changes: 17 additions & 4 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package server
import (
"context"
"fmt"
"github.com/JensvandeWiel/ArkAscendedServerManager/helpers"
"github.com/keybase/go-ps"
"github.com/wailsapp/wails/v2/pkg/runtime"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/JensvandeWiel/ArkAscendedServerManager/helpers"
"github.com/keybase/go-ps"
"github.com/wailsapp/wails/v2/pkg/runtime"
)

// Server contains the server "stuff"
Expand Down Expand Up @@ -69,6 +70,9 @@ type Server struct {
MaxPlayers int `json:"maxPlayers"`

StartWithApplication bool `json:"startWithApplication"`

AutoSaveEnabled bool `json:"autoSaveEnabled"`
AutoSaveInterval int `json:"autoSaveInterval"`
}

// UpdateConfig updates the configuration files for the server e.g.: GameUserSettings.ini
Expand Down Expand Up @@ -182,7 +186,7 @@ func (s *Server) Stop() error {
}
}

_, err := s.helpers.SendRconCommand("saveworld", s.IpAddress, s.RCONPort, s.AdminPassword)
err := s.SaveWorld()
if err != nil {
return err
}
Expand Down Expand Up @@ -258,3 +262,12 @@ func (s *Server) CreateArguments() []string {

return args
}

// save the world
func (s *Server) SaveWorld() error {
_, err := s.helpers.SendRconCommand("saveworld", s.IpAddress, s.RCONPort, s.AdminPassword)
if err != nil {
return err
}
return nil
}
74 changes: 66 additions & 8 deletions server/server_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/JensvandeWiel/ArkAscendedServerManager/helpers"
"github.com/adrg/xdg"
"github.com/wailsapp/wails/v2/pkg/runtime"
"os"
"path"
"strconv"
"time"

"github.com/JensvandeWiel/ArkAscendedServerManager/helpers"
"github.com/adrg/xdg"
"github.com/wailsapp/wails/v2/pkg/runtime"
)

const (
Expand All @@ -29,10 +31,11 @@ const (

// ServerController struct
type ServerController struct {
ctx context.Context
Servers map[int]*Server
helpers *helpers.HelpersController
serverDir string
ctx context.Context
Servers map[int]*Server
helpers *helpers.HelpersController
autoSaveIterations int
serverDir string
}

//region Struct Initialization and Creation
Expand All @@ -57,8 +60,12 @@ func (c *ServerController) Startup(ctx context.Context) {
c.serverDir = serverDir

c.StartServersWithApplication()
c.RunAutoSaveTimers()
}

// endregion

// region Backend Functions
func (c *ServerController) StartServersWithApplication() {
servers, err := c.getAllServers()
if err != nil {
Expand All @@ -69,13 +76,64 @@ func (c *ServerController) StartServersWithApplication() {

for id := range servers {
server := c.Servers[id]
runtime.LogInfof(c.ctx, "StartWithApplication: %t", server.StartWithApplication)
runtime.LogInfof(c.ctx, "Starting server %s automatically", server.ServerName)
if server.StartWithApplication {
c.StartServer(server.Id)
}
}
}

// start repeating timer that calls auto-save
// having one timer that manages all servers is advantageous:
// - catches conditions where a user enables auto-save after the timer has started
// - catches interval changes made after the timer has started
func (c *ServerController) RunAutoSaveTimers() {
c.autoSaveIterations = 0

autoSave := time.NewTicker(time.Minute)
for {
select {
case <-autoSave.C:
c.AutoSaveServers()
default:
continue
}
}
}

func (c *ServerController) AutoSaveServers() {
servers, err := c.getAllServers()
if err != nil {
newErr := fmt.Errorf("Error getting all servers " + err.Error())
runtime.LogErrorf(c.ctx, newErr.Error())
return
}

c.autoSaveIterations += 1
// seconds in a minute * hours in a day * days, increase days if more days are required
// d
if c.autoSaveIterations == (60 * 24 * 7) { // one week in seconds
// very early max int catch (definitely extendable in the future if necessary)
c.autoSaveIterations = 0
}

for id := range servers {
server := c.Servers[id]
if server.AutoSaveEnabled {
// if interval is multiple of iterations
if c.autoSaveIterations%server.AutoSaveInterval == 0 {
runtime.LogInfo(c.ctx, "Running autosave for "+server.ServerName)

err = server.SaveWorld()
if err != nil {
newErr := fmt.Errorf("Server auto-save created an error: " + err.Error())
runtime.LogErrorf(c.ctx, newErr.Error())
}
}
}
}
}

//endregion

//region Frontend functions
Expand Down
Loading