diff --git a/README.md b/README.md index 38b9a643..8234bc52 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,12 @@ An open-source, minimal, configurable, fast bootstrapper for running Roblox on L + Roblox's logs appear within Vinegar + FPS Unlocking for Player by default, without rbxfpsunlocker + Browser launch via MIME ++ Automatic [GameMode](https://github.com/FeralInteractive/gamemode) functionality + Custom execution of wine program within wineprefix + TOML configuration file + Force a specific version of Roblox + Select/Force Roblox release channels, lets you opt into non-production Roblox release channels - + Custom launcher specified to be used when launching Roblox (eg. [GameMode](https://github.com/FeralInteractive/gamemode)). + + Custom launcher specified to be used when launching Roblox + Wine Root, allows you to set a specific wine installation path + Sanitization of environment + Set different environment variables and FFlags for both Player and Studio diff --git a/cmd/vinegar/binary.go b/cmd/vinegar/binary.go index ab60482f..2cc788bd 100644 --- a/cmd/vinegar/binary.go +++ b/cmd/vinegar/binary.go @@ -16,6 +16,7 @@ import ( bsrpc "github.com/vinegarhq/vinegar/bloxstraprpc" "github.com/vinegarhq/vinegar/config" + "github.com/vinegarhq/vinegar/internal/bus" "github.com/vinegarhq/vinegar/internal/dirs" "github.com/vinegarhq/vinegar/internal/state" "github.com/vinegarhq/vinegar/roblox" @@ -49,6 +50,9 @@ type Binary struct { // Logging Auth bool Activity bsrpc.Activity + + // DBUS session + BusSession *bus.SessionBus } func NewBinary(bt roblox.BinaryType, cfg *config.Config, pfx *wine.Prefix) *Binary { @@ -71,6 +75,8 @@ func NewBinary(bt roblox.BinaryType, cfg *config.Config, pfx *wine.Prefix) *Bina Name: bt.BinaryName(), Type: bt, Prefix: pfx, + + BusSession: bus.New(), } } @@ -122,6 +128,16 @@ func (b *Binary) Run(args ...string) error { log.Printf("Launching %s", b.Name) b.Splash.SetMessage("Launching " + b.Alias) + if err := cmd.Start(); err != nil { + return fmt.Errorf("roblox process: %w", err) + } + + if b.Config.GameMode { + if err := b.BusSession.GamemodeRegister(int32(cmd.Process.Pid)); err != nil { + fmt.Fprintf(os.Stderr, "failed to register gamemode: %s", err.Error()) + } + } + defer func() { // Don't do anything if the process even ran correctly. if cmd.Process == nil { @@ -149,7 +165,7 @@ func (b *Binary) Run(args ...string) error { b.Prefix.Kill() }() - if err := cmd.Run(); err != nil { + if err := cmd.Wait(); err != nil { return fmt.Errorf("roblox process: %w", err) } diff --git a/config/config.go b/config/config.go index 32846ee3..035363e9 100644 --- a/config/config.go +++ b/config/config.go @@ -35,6 +35,7 @@ type Binary struct { FFlags roblox.FFlags `toml:"fflags"` Env Environment `toml:"env"` ForcedGpu string `toml:"gpu"` + GameMode bool `toml:"gamemode"` } type Config struct { @@ -113,6 +114,7 @@ func Default() Config { Player: Binary{ DiscordRPC: true, Dxvk: true, + GameMode: true, FFlags: roblox.FFlags{ "DFIntTaskSchedulerTargetFps": 640, }, @@ -121,7 +123,8 @@ func Default() Config { }, }, Studio: Binary{ - Dxvk: true, + Dxvk: true, + GameMode: true, }, Splash: Splash{ diff --git a/go.mod b/go.mod index 6ee52aba..b34d163b 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 // indirect gioui.org/shader v1.0.8 // indirect github.com/go-text/typesetting v0.0.0-20231101082850-a36c1d9288f6 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/exp/shiny v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/image v0.13.0 // indirect diff --git a/go.sum b/go.sum index 7f8a5e1d..a5330b89 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/go-text/typesetting v0.0.0-20231101082850-a36c1d9288f6 h1:1DDZ2Nr1mno github.com/go-text/typesetting v0.0.0-20231101082850-a36c1d9288f6/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k= github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22 h1:LBQTFxP2MfsyEDqSKmUBZaDuDHN1vpqDyOZjcqS7MYI= github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/hugolgst/rich-go v0.0.0-20230917173849-4a4fb1d3c362 h1:Q8D2HP1l2mOoeRVLhHjDhK8MRb7LkjESWRtd2gbauws= github.com/hugolgst/rich-go v0.0.0-20230917173849-4a4fb1d3c362/go.mod h1:nGaW7CGfNZnhtiFxMpc4OZdqIexGXjUlBnlmpZmjEKA= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= diff --git a/internal/bus/bus.go b/internal/bus/bus.go new file mode 100644 index 00000000..3c1842db --- /dev/null +++ b/internal/bus/bus.go @@ -0,0 +1,37 @@ +package bus + +import ( + "errors" + + "github.com/godbus/dbus/v5" +) + +type SessionBus struct { + conn *dbus.Conn + portal dbus.BusObject +} + +func New() *SessionBus { + conn, err := dbus.ConnectSessionBus() + if err != nil { + return &SessionBus{} + } + + return &SessionBus{ + conn: conn, + portal: conn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"), + } +} + +func (s *SessionBus) GamemodeRegister(pid int32) error { + if s.conn == nil { + return nil + } + + call := s.portal.Call("org.freedesktop.portal.GameMode.RegisterGame", 0, pid) + if call.Err != nil && !errors.Is(call.Err, dbus.ErrMsgNoObject) { + return call.Err + } + + return nil +}