This repository has been archived on 2022-06-29. You can view files and clone it, but cannot push or open issues or pull requests.
urtrator/launcher/launcher_object.go

154 lines
4.7 KiB
Go

// URTrator - Urban Terror server browser and game launcher, written in
// Go.
//
// Copyright (c) 2016-2020, Stanslav N. a.k.a pztrn (or p0z1tr0n) and
// URTrator contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package launcher
import (
// stdlib
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
// local
"go.dev.pztrn.name/urtrator/datamodels"
// Github
"github.com/mattn/go-gtk/gtk"
)
type Launcher struct {
// Flags.
// Is Urban Terror launched ATM?
launched bool
}
func (l *Launcher) CheckForLaunchedUrbanTerror() error {
if l.launched {
// Temporary disable all these modals on Linux.
// See https://github.com/mattn/go-gtk/issues/289.
if runtime.GOOS != "linux" {
mbox_string := "Game is launched.\n\nCannot quit, because game is launched.\nQuit Urban Terror to exit URTrator!"
m := gtk.NewMessageDialog(nil, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
m.Response(func() {
m.Destroy()
})
m.Run()
return errors.New("User didn't select valid profile, mismatch with server's version.")
}
}
return nil
}
func (l *Launcher) findFreeDisplay() string {
current_display_raw := os.Getenv("DISPLAY")
current_display, _ := strconv.Atoi(strings.Split(current_display_raw, ":")[1])
current_display += 1
return strconv.Itoa(current_display)
}
func (l *Launcher) Initialize() {
fmt.Println("Initializing game launcher...")
}
func (l *Launcher) Launch(server_profile *datamodels.Server, user_profile *datamodels.Profile, password string, additional_parameters []string, callback func()) {
// ToDo: only one instance of Urban Terror should be launched, so button
// should be disabled.
fmt.Println("Launching Urban Terror...")
done := make(chan bool, 1)
// Create launch string.
var launch_bin string = ""
launch_bin, err := exec.LookPath(user_profile.Binary)
if err != nil {
fmt.Println(err.Error())
}
server_address := server_profile.Ip + ":" + server_profile.Port
var launch_params []string
if len(server_address) > 0 {
launch_params = append(launch_params, "+connect", server_address)
}
if len(password) > 0 {
launch_params = append(launch_params, "+password", password)
}
if len(user_profile.Additional_params) > 0 {
additional_params := strings.Split(user_profile.Additional_params, " ")
launch_params = append(launch_params, additional_params...)
}
if len(additional_parameters) > 0 {
for i := range additional_parameters {
launch_params = append(launch_params, additional_parameters[i])
}
}
if runtime.GOOS == "linux" && user_profile.Second_x_session == "1" {
launch_params = append([]string{launch_bin}, launch_params...)
display := l.findFreeDisplay()
launch_bin, err = exec.LookPath("xinit")
if err != nil {
fmt.Println(err.Error())
}
launch_params = append(launch_params, "--", ":"+display)
}
if runtime.GOOS == "darwin" {
// On macOS we should not start binary, but application bundle.
// So we will obtain app bundle path.
bundle_path := strings.Split(launch_bin, "/Contents")[0]
// and create special launch string, which involves open.
launch_bin = "/usr/bin/open"
launch_params = append([]string{launch_bin, "-W", "-a", bundle_path, "--args"}, launch_params...)
}
fmt.Println(launch_bin, launch_params)
go func() {
go func() {
cmd := exec.Command(launch_bin, launch_params...)
// This workaround is required on Windows, otherwise ioq3
// will not find game data.
if runtime.GOOS == "windows" {
dir := filepath.Dir(launch_bin)
cmd.Dir = dir
}
out, err1 := cmd.Output()
if err1 != nil {
fmt.Println("Launch error: " + err1.Error())
}
fmt.Println(string(out))
done <- true
}()
select {
case <-done:
callback()
}
}()
}