From c063f12dfaaa4d00443bec7cceff41662685cc94 Mon Sep 17 00:00:00 2001 From: Leigh MacDonald Date: Thu, 2 Mar 2023 18:15:26 -0700 Subject: [PATCH 1/2] Enables auto-start game on launch and auto-close on game exit --- go.mod | 1 + go.sum | 12 ++----- internal/detector/application.go | 51 ++++++++++++++++++++------- internal/model/consts.go | 1 + internal/model/gui.go | 1 + internal/model/settings.go | 6 +++- internal/platform/windows.go | 15 ++++++++ internal/translations/active.en.yaml | 13 +++++++ internal/translations/translations.go | 4 +++ internal/ui/settings.go | 11 ++++++ internal/ui/ui.go | 4 +++ main.go | 1 + 12 files changed, 96 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index ea00873..29eaa66 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/leighmacdonald/steamweb v0.0.4 github.com/mattn/go-sqlite3 v1.14.16 github.com/mitchellh/go-homedir v1.1.0 + github.com/mitchellh/go-ps v1.0.0 github.com/nicksnyder/go-i18n/v2 v2.2.1 github.com/nxadm/tail v1.4.8 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index e989c37..10067a2 100644 --- a/go.sum +++ b/go.sum @@ -870,7 +870,6 @@ github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY9 github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -1287,6 +1286,8 @@ github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXx github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -1394,9 +1395,7 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.2/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= @@ -1516,7 +1515,6 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.9.4 h1:Sd43wM1IWz/s1aVXdOBkjJvuP8UdyqioeE4AmM0QsBs= github.com/spf13/afero v1.9.4/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= @@ -1571,7 +1569,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -1770,8 +1767,6 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= -golang.org/x/mobile v0.0.0-20221110043201-43a038452099 h1:aIu0lKmfdgtn2uTj7JI2oN4TUrQvgB+wzTPO23bCKt8= -golang.org/x/mobile v0.0.0-20221110043201-43a038452099/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY= golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c h1:Gk61ECugwEHL6IiyyNLXNzmu8XslmRP2dS0xjIYhbb4= golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -2589,15 +2584,12 @@ modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= -modernc.org/sqlite v1.20.4 h1:J8+m2trkN+KKoE7jglyHYYYiaq5xmz2HoHJIiBlRzbE= -modernc.org/sqlite v1.20.4/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A= modernc.org/sqlite v1.21.0 h1:4aP4MdUf15i3R3M2mx6Q90WHKz3nZLoz96zlB6tNdow= modernc.org/sqlite v1.21.0/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= -modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/internal/detector/application.go b/internal/detector/application.go index 6bd2865..98b7440 100644 --- a/internal/detector/application.go +++ b/internal/detector/application.go @@ -61,6 +61,7 @@ type BD struct { gameStateUpdate chan updateGameStateEvent cache cache.FsCache startupTime time.Time + gameHasStartedOnce bool richPresenceActive bool } @@ -69,19 +70,20 @@ func New(settings *model.Settings, store store.DataStore, rules *rules.Engine, c logChan := make(chan string) eventChan := make(chan model.LogEvent) rootApp := BD{ - store: store, - rules: rules, - settings: settings, - logChan: logChan, - incomingLogEvents: eventChan, - serverMu: &sync.RWMutex{}, - players: model.PlayerCollection{}, - playersMu: &sync.RWMutex{}, - triggerUpdate: make(chan any), - gameStateUpdate: make(chan updateGameStateEvent, 50), - cache: cache, - logParser: newLogParser(logChan, eventChan), - startupTime: time.Now(), + store: store, + rules: rules, + settings: settings, + logChan: logChan, + incomingLogEvents: eventChan, + serverMu: &sync.RWMutex{}, + players: model.PlayerCollection{}, + playersMu: &sync.RWMutex{}, + triggerUpdate: make(chan any), + gameStateUpdate: make(chan updateGameStateEvent, 50), + cache: cache, + logParser: newLogParser(logChan, eventChan), + startupTime: time.Now(), + gameHasStartedOnce: platform.IsGameRunning(), } rootApp.createLogReader() @@ -295,6 +297,7 @@ func (bd *BD) LaunchGameAndWait() { log.Println(errArgs) return } + bd.gameHasStartedOnce = true if errLaunch := platform.LaunchTF2(bd.settings.TF2Dir, args); errLaunch != nil { log.Printf("Failed to launch game: %v\n", errLaunch) } @@ -924,6 +927,24 @@ func (bd *BD) CallVote(ctx context.Context, userID int64, reason model.KickReaso return nil } +func (bd *BD) processChecker(ctx context.Context) { + ticker := time.NewTicker(model.DurationProcessTimeout) + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + if !bd.gameHasStartedOnce || !bd.settings.AutoCloseOnGameExit { + continue + } + if !platform.IsGameRunning() { + log.Printf("Auto-closing on game exit\n") + bd.gui.Quit() + } + } + } +} + // Shutdown closes any open rcon connection and will flush any player list to disk func (bd *BD) Shutdown() { if bd.rconConnection != nil { @@ -944,5 +965,9 @@ func (bd *BD) Start(ctx context.Context) { go bd.eventHandler() go bd.gameStateTracker(ctx) go bd.statusUpdater(ctx) + go bd.processChecker(ctx) + if !bd.gameHasStartedOnce && bd.settings.AutoLaunchGame && !platform.IsGameRunning() { + go bd.LaunchGameAndWait() + } <-ctx.Done() } diff --git a/internal/model/consts.go b/internal/model/consts.go index 3a78fc8..e53054c 100644 --- a/internal/model/consts.go +++ b/internal/model/consts.go @@ -16,6 +16,7 @@ const ( DurationCacheTimeout = time.Hour * 12 DurationWebRequestTimeout = time.Second * 5 DurationRCONRequestTimeout = time.Second + DurationProcessTimeout = time.Second * 3 ) type Team int diff --git a/internal/model/gui.go b/internal/model/gui.go index b323a06..b1af02b 100644 --- a/internal/model/gui.go +++ b/internal/model/gui.go @@ -8,6 +8,7 @@ import ( type UserInterface interface { Refresh() Start(ctx context.Context) + Quit() UpdateServerState(state Server) UpdatePlayerState(collection PlayerCollection) AddUserMessage(message UserMessage) diff --git a/internal/model/settings.go b/internal/model/settings.go index 18133f6..ec0e72a 100644 --- a/internal/model/settings.go +++ b/internal/model/settings.go @@ -70,13 +70,15 @@ type Settings struct { SteamDir string `yaml:"steam_dir"` // Path to tf2 mod (C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf) TF2Dir string `yaml:"tf2_dir"` + AutoLaunchGame bool `yaml:"auto_launch_game_auto"` + AutoCloseOnGameExit bool `yaml:"auto_close_on_game_exit"` ApiKey string `yaml:"api_key"` DisconnectedTimeout string `yaml:"disconnected_timeout"` DiscordPresenceEnabled bool `yaml:"discord_presence_enabled"` KickerEnabled bool `yaml:"kicker_enabled"` ChatWarningsEnabled bool `yaml:"chat_warnings_enabled"` PartyWarningsEnabled bool `yaml:"party_warnings_enabled"` - KickTags []string `json:"kick_tags"` + KickTags []string `yaml:"kick_tags"` Lists ListConfigCollection `yaml:"lists"` Links []LinkConfig `yaml:"links"` RconStatic bool `yaml:"rcon_static"` @@ -131,6 +133,8 @@ func NewSettings() (*Settings, error) { DisconnectedTimeout: "60s", DiscordPresenceEnabled: true, KickerEnabled: false, + AutoCloseOnGameExit: false, + AutoLaunchGame: false, KickTags: []string{"cheater", "bot", "trigger_name", "trigger_msg"}, ChatWarningsEnabled: false, PartyWarningsEnabled: true, diff --git a/internal/platform/windows.go b/internal/platform/windows.go index 5a2b3c0..b949d95 100644 --- a/internal/platform/windows.go +++ b/internal/platform/windows.go @@ -5,6 +5,7 @@ package platform import ( "github.com/andygrunwald/vdf" "github.com/leighmacdonald/golib" + "github.com/mitchellh/go-ps" "github.com/pkg/errors" "golang.org/x/sys/windows/registry" "log" @@ -98,6 +99,20 @@ func OpenFolder(dir string) { } } +func IsGameRunning() bool { + processes, errPs := ps.Processes() + if errPs != nil { + log.Printf("Failed to get process list: %v\n", errPs) + return false + } + for _, process := range processes { + if process.Executable() == BinaryName { + return true + } + } + return false +} + func init() { foundSteamRoot, errFoundSteamRoot := getSteamRoot() if errFoundSteamRoot == nil && golib.Exists(foundSteamRoot) { diff --git a/internal/translations/active.en.yaml b/internal/translations/active.en.yaml index 34755c5..598f2a8 100644 --- a/internal/translations/active.en.yaml +++ b/internal/translations/active.en.yaml @@ -118,6 +118,19 @@ label_settings_discord_presence: label_settings_discord_presence_hint: one: "Enables discord rich presence if discord is running" +label_auto_close_on_game_exit: + one: "Auto Close" + +label_auto_close_on_game_exit_hint: + one: "When TF2 exits, close bd as well" + +label_auto_launch_game: + one: "Auto Launch TF2" + +label_auto_launch_game_hint: + one: "When launching bd, also automatically launch tf2" + + label_settings_steam_api_key: one: "Steam API Key" diff --git a/internal/translations/translations.go b/internal/translations/translations.go index 8a3084f..f76a051 100644 --- a/internal/translations/translations.go +++ b/internal/translations/translations.go @@ -60,6 +60,10 @@ const ( LabelSettingsPartyWarnings Key = "label_settings_party_warnings" LabelSettingsPartyWarningsHint Key = "label_settings_party_warnings_hint" LabelSettingsDiscordPresence Key = "label_settings_discord_presence" + LabelAutoCloseOnGameExit Key = "label_auto_close_on_game_exit" + LabelAutoCloseOnGameExitHint Key = "label_auto_close_on_game_exit_hint" + LabelAutoLaunchGame Key = "label_auto_launch_game" + LabelAutoLaunchGameHint Key = "label_auto_launch_game_hint" LabelSettingsDiscordPresenceHint Key = "label_settings_discord_presence_hint" LabelSettingsSteamApiKey Key = "label_settings_steam_api_key" LabelSettingsSteamApiKeyHint Key = "label_settings_steam_api_key_hint" diff --git a/internal/ui/settings.go b/internal/ui/settings.go index 8b4a681..cf3ea13 100644 --- a/internal/ui/settings.go +++ b/internal/ui/settings.go @@ -118,6 +118,11 @@ func newSettingsDialog(parent fyne.Window, boundSettings boundSettings, settings } return nil } + autoCloseOnGameExit := boundSettings.getBoundBoolDefault("AutoCloseOnGameExit", true) + autoCloseOnGameExitEntry := widget.NewCheckWithData("", autoCloseOnGameExit) + + autoLaunchGame := boundSettings.getBoundBoolDefault("AutoLaunchGame", true) + autoLaunchGameEntry := widget.NewCheckWithData("", autoLaunchGame) kickerEnabled := boundSettings.getBoundBoolDefault("KickerEnabled", true) kickerEnabledEntry := widget.NewCheckWithData("", kickerEnabled) @@ -155,6 +160,10 @@ func newSettingsDialog(parent fyne.Window, boundSettings boundSettings, settings HintText: translations.One(translations.LabelSettingsPartyWarningsHint)}, {Text: translations.One(translations.LabelSettingsDiscordPresence), Widget: discordPresenceEnabledEntry, HintText: translations.One(translations.LabelSettingsDiscordPresenceHint)}, + {Text: translations.One(translations.LabelAutoLaunchGame), Widget: autoLaunchGameEntry, + HintText: translations.One(translations.LabelAutoLaunchGameHint)}, + {Text: translations.One(translations.LabelAutoCloseOnGameExit), Widget: autoCloseOnGameExitEntry, + HintText: translations.One(translations.LabelAutoCloseOnGameExitHint)}, {Text: translations.One(translations.LabelSettingsSteamApiKey), Widget: apiKeyEntry, HintText: translations.One(translations.LabelSettingsSteamApiKeyHint)}, {Text: translations.One(translations.LabelSettingsSteamId), Widget: steamIdEntry, @@ -206,6 +215,8 @@ func newSettingsDialog(parent fyne.Window, boundSettings boundSettings, settings settings.ChatWarningsEnabled = chatWarningsEnabledEntry.Checked settings.PartyWarningsEnabled = partyWarningsEnabledEntry.Checked settings.RconStatic = rconModeStaticEntry.Checked + settings.AutoCloseOnGameExit = autoCloseOnGameExitEntry.Checked + settings.AutoLaunchGame = autoLaunchGameEntry.Checked settings.Unlock() if apiKeyOriginal != apiKeyEntry.Text { if errSetKey := steamweb.SetKey(apiKeyEntry.Text); errSetKey != nil { diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 22b3e99..d8f4c76 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -203,6 +203,10 @@ func (ui *Ui) Start(ctx context.Context) { ctx.Done() } +func (ui *Ui) Quit() { + ui.application.Quit() +} + func showUserError(msg error, parent fyne.Window) { d := dialog.NewError(msg, parent) d.Show() diff --git a/main.go b/main.go index 9e7e365..ed4dfdd 100644 --- a/main.go +++ b/main.go @@ -32,6 +32,7 @@ func main() { if errSettings != nil { log.Panicf("Failed to initialize settings: %v", errSettings) } + localRules := rules.NewRuleSchema() localPlayersList := rules.NewPlayerListSchema() if errReadSettings := settings.ReadDefaultOrCreate(); errReadSettings != nil { From 22b95f930d3e98ed62530e1099d7831cb5b951a6 Mon Sep 17 00:00:00 2001 From: Leigh MacDonald Date: Thu, 2 Mar 2023 18:16:17 -0700 Subject: [PATCH 2/2] Add linux process check --- internal/platform/linux.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/platform/linux.go b/internal/platform/linux.go index 680614a..f0df171 100644 --- a/internal/platform/linux.go +++ b/internal/platform/linux.go @@ -12,6 +12,7 @@ import ( var ( DefaultSteamRoot = "~/.local/share/steam/Steam" DefaultTF2Root = "~/.local/share/steam/Steam/steamapps/common/Team Fortress 2/tf" + BinaryName = "hl2" TF2RootValidationFile = "bin/client.so" ) @@ -35,6 +36,20 @@ func OpenFolder(dir string) { } } +func IsGameRunning() bool { + processes, errPs := ps.Processes() + if errPs != nil { + log.Printf("Failed to get process list: %v\n", errPs) + return false + } + for _, process := range processes { + if process.Executable() == BinaryName { + return true + } + } + return false +} + func init() { // We cant really auto-detect this stuff in the same manner line on windows with the registry // so linux users may need to configure this manually.