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

Commit

Permalink
#121: Auto-Save (#122)
Browse files Browse the repository at this point in the history
This commit adds auto-saving functionality. This feature can
be enabled / disabled, with a
configurable interval.

Co-authored-by: Jordan Dalby <jordan.dalby@outlook.com>
  • Loading branch information
jordan-dalby and Jordan Dalby committed Nov 18, 2023
1 parent 5492eef commit 933d09a
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 14 deletions.
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

0 comments on commit 933d09a

Please sign in to comment.