Skip to content
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
9 changes: 8 additions & 1 deletion UIMod/ui/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ <h3 class="section-title">Advanced Configuration</h3>
value="{{AdditionalParams}}">
<div class="input-info">Format: CustomParam1 Value1 CustomParam2 Value2</div>
</div>

<div class="form-group">
<label for="AutoRestartServerTimer">Scheduled Gameserver Restart:</label>
<input type="text" id="AutoRestartServerTimer" name="AutoRestartServerTimer"
value="{{AutoRestartServerTimer}}">
<div class="input-info">Timeframe in <strong> minutes </strong> to schedule an automatic gameserver restart. 0 = disabled, 1440 = 24 hours, etc.. If SSCM is enabled, you will see "Attention, server is restarting in 30/20/10/5 seconds!" messages <strong> ingame </strong> before restarting.</div>
</div>
</div>
</div>

Expand All @@ -221,7 +228,7 @@ <h3 class="section-title">Advanced Configuration</h3>
<button type="button" class="save-button"
onclick="document.getElementById('server-config-form').submit()"></button>
</div>
</form>
</form>
</div>
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

var (
// All configuration variables can be found in vars.go
Version = "5.4.31"
Version = "5.4.32"
Branch = "release"
)

Expand Down Expand Up @@ -63,6 +63,7 @@ type JsonConfig struct {
SubsystemFilters []string `json:"subsystemFilters"`
IsUpdateEnabled *bool `json:"IsUpdateEnabled"`
IsSSCMEnabled *bool `json:"IsSSCMEnabled"`
AutoRestartServerTimer string `json:"AutoRestartServerTimer"`
AllowPrereleaseUpdates *bool `json:"AllowPrereleaseUpdates"`
AllowMajorUpdates *bool `json:"AllowMajorUpdates"`
}
Expand Down Expand Up @@ -202,7 +203,7 @@ func applyConfig(cfg *JsonConfig) {
cfg.AllowMajorUpdates = &allowMajorUpdatesVal

SubsystemFilters = getStringSlice(cfg.SubsystemFilters, "SUBSYSTEM_FILTERS", []string{})

AutoRestartServerTimer = getString(cfg.AutoRestartServerTimer, "AUTO_RESTART_SERVER_TIMER", "0")
isSSCMEnabledVal := getBool(cfg.IsSSCMEnabled, "IS_SSCM_ENABLED", false)
IsSSCMEnabled = isSSCMEnabledVal
cfg.IsSSCMEnabled = &isSSCMEnabledVal
Expand Down
27 changes: 14 additions & 13 deletions src/config/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,20 @@ var (

// Logging, debugging and misc
var (
IsDebugMode bool //only used for pprof server, keep it like this and check the log level instead. Debug = 10
CreateSSUILogFile bool
LogLevel int
LogMessageBuffer string
IsFirstTimeSetup bool
BufferFlushTicker *time.Ticker
SSEMessageBufferSize = 2000
MaxSSEConnections = 20
GameServerAppID = "600760"
ExePath string
GameBranch string
SubsystemFilters []string
GameServerUUID uuid.UUID // Assined at startup to the current instance of the server we are managing. Currently unused.
IsDebugMode bool //only used for pprof server, keep it like this and check the log level instead. Debug = 10
CreateSSUILogFile bool
LogLevel int
LogMessageBuffer string
IsFirstTimeSetup bool
BufferFlushTicker *time.Ticker
SSEMessageBufferSize = 2000
MaxSSEConnections = 20
GameServerAppID = "600760"
ExePath string
GameBranch string
SubsystemFilters []string
GameServerUUID uuid.UUID // Assined at startup to the current instance of the server we are managing. Currently unused.
AutoRestartServerTimer string
)

// Discord integration
Expand Down
75 changes: 71 additions & 4 deletions src/gamemgr/processmanagement.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import (
"syscall"
"time"

"github.com/JacksonTheMaster/StationeersServerUI/v5/src/commandmgr"
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/config"
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/logger"
"github.com/google/uuid"
)

var (
cmd *exec.Cmd
mu sync.Mutex
logDone chan struct{}
err error
cmd *exec.Cmd
mu sync.Mutex
logDone chan struct{}
err error
autoRestartDone chan struct{}
)

// InternalIsServerRunning checks if the server process is running.
Expand Down Expand Up @@ -163,6 +165,17 @@ func InternalStartServer() error {
// create a UUID for this specific run
createGameServerUUID()
logger.Core.Debug("Created Game Server with internal UUID: " + config.GameServerUUID.String())

// Start auto-restart goroutine if AutoRestartServerTimer is set greater than 0
if config.AutoRestartServerTimer != "0" {
if autoRestartDone != nil {
close(autoRestartDone)
}
autoRestartDone = make(chan struct{})
go startAutoRestart(config.AutoRestartServerTimer, autoRestartDone)
logger.Core.Info("Auto-restart scheduled every " + config.AutoRestartServerTimer + " minutes")
}

return nil
}

Expand All @@ -174,6 +187,13 @@ func InternalStopServer() error {
return fmt.Errorf("server not running")
}

// Stop auto-restart goroutine
if autoRestartDone != nil {
close(autoRestartDone)
autoRestartDone = nil
logger.Core.Info("Auto-restart cycle interrupted due to manaual stop")
}

// Process is running, stop it
isWindows := runtime.GOOS == "windows"
var killErr error
Expand Down Expand Up @@ -247,6 +267,53 @@ func InternalStopServer() error {
return nil
}

// startAutoRestart runs a goroutine that restarts the server after the specified timeframe in minutes.
func startAutoRestart(minutes string, done chan struct{}) {
minutesInt, _ := strconv.Atoi(minutes)
ticker := time.NewTicker(time.Duration(minutesInt) * time.Minute)
defer ticker.Stop()

for {
select {
case <-ticker.C:
mu.Lock()
if !internalIsServerRunningNoLock() {
mu.Unlock()
logger.Core.Info("Auto-restart skipped: server is not running")
return
}
mu.Unlock()

if config.IsSSCMEnabled {
commandmgr.WriteCommand("say Attention, server is restarting in 30 seconds!")
time.Sleep(10 * time.Second)
commandmgr.WriteCommand("say Attention, server is restarting in 20 seconds!")
time.Sleep(10 * time.Second)
commandmgr.WriteCommand("say Attention, server is restarting in 10 seconds!")
time.Sleep(5 * time.Second)
commandmgr.WriteCommand("say Attention, server is restarting in 5 seconds!")
time.Sleep(5 * time.Second)
}
logger.Core.Info("Auto-restart triggered: stopping server")
if err := InternalStopServer(); err != nil {
logger.Core.Error("Auto-restart failed to stop server: " + err.Error())
return
}

logger.Core.Info("Auto-restart: waiting 5 seconds before restarting")
time.Sleep(5 * time.Second)

logger.Core.Info("Auto-restart: starting server")
if err := InternalStartServer(); err != nil {
logger.Core.Error("Auto-restart failed to start server: " + err.Error())
return
}
case <-done:
return
}
}
}

func clearGameServerUUID() {
config.ConfigMu.Lock()
defer config.ConfigMu.Unlock()
Expand Down
1 change: 1 addition & 0 deletions src/web/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) {
"{{UseSteamP2PFalseSelected}}": steamP2PFalseSelected,
"{{ExePath}}": config.ExePath,
"{{AdditionalParams}}": config.AdditionalParams,
"{{AutoRestartServerTimer}}": config.AutoRestartServerTimer,
}

for placeholder, value := range replacements {
Expand Down
Loading