added vanilla-tweaks
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
var EnableMetalHud = true // Default to enabled
|
var EnableMetalHud = true // Default to enabled
|
||||||
var CustomEnvVars = "" // Custom environment variables
|
var CustomEnvVars = "" // Custom environment variables
|
||||||
|
var EnableVanillaTweaks = false // Default to disabled
|
||||||
|
|
||||||
// Terminal state management
|
// Terminal state management
|
||||||
var (
|
var (
|
||||||
@@ -132,10 +133,36 @@ func LaunchGame(myWindow fyne.Window) {
|
|||||||
|
|
||||||
log.Println("Preparing to launch TurtleSilicon...")
|
log.Println("Preparing to launch TurtleSilicon...")
|
||||||
|
|
||||||
|
// Determine which WoW executable to use based on vanilla-tweaks preference
|
||||||
|
var wowExePath string
|
||||||
|
if EnableVanillaTweaks {
|
||||||
|
if !CheckForWoWTweakedExecutable() {
|
||||||
|
// Show dialog asking if user wants us to apply vanilla-tweaks
|
||||||
|
HandleVanillaTweaksRequest(myWindow, func() {
|
||||||
|
// After successful patching, continue with launch using the tweaked executable
|
||||||
|
wowTweakedExePath := GetWoWTweakedExecutablePath()
|
||||||
|
if wowTweakedExePath != "" {
|
||||||
|
continueLaunch(myWindow, wowTweakedExePath)
|
||||||
|
} else {
|
||||||
|
dialog.ShowError(fmt.Errorf("failed to find WoW-tweaked.exe after patching"), myWindow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return // Exit early since dialog will handle the continuation
|
||||||
|
}
|
||||||
|
wowExePath = GetWoWTweakedExecutablePath()
|
||||||
|
} else {
|
||||||
|
wowExePath = filepath.Join(paths.TurtlewowPath, "WoW.exe")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with normal launch process
|
||||||
|
continueLaunch(myWindow, wowExePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// continueLaunch continues the game launch process with the specified executable
|
||||||
|
func continueLaunch(myWindow fyne.Window, wowExePath string) {
|
||||||
rosettaInTurtlePath := filepath.Join(paths.TurtlewowPath, "rosettax87")
|
rosettaInTurtlePath := filepath.Join(paths.TurtlewowPath, "rosettax87")
|
||||||
rosettaExecutable := filepath.Join(rosettaInTurtlePath, "rosettax87")
|
rosettaExecutable := filepath.Join(rosettaInTurtlePath, "rosettax87")
|
||||||
wineloader2Path := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
|
wineloader2Path := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
|
||||||
wowExePath := filepath.Join(paths.TurtlewowPath, "wow.exe") // Corrected to wow.exe
|
|
||||||
|
|
||||||
if !utils.PathExists(rosettaExecutable) {
|
if !utils.PathExists(rosettaExecutable) {
|
||||||
dialog.ShowError(fmt.Errorf("rosetta executable not found at %s. Ensure TurtleWoW patching was successful", rosettaExecutable), myWindow)
|
dialog.ShowError(fmt.Errorf("rosetta executable not found at %s. Ensure TurtleWoW patching was successful", rosettaExecutable), myWindow)
|
||||||
@@ -146,7 +173,7 @@ func LaunchGame(myWindow fyne.Window) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !utils.PathExists(wowExePath) {
|
if !utils.PathExists(wowExePath) {
|
||||||
dialog.ShowError(fmt.Errorf("wow.exe not found at %s. Ensure your TurtleWoW directory is correct", wowExePath), myWindow)
|
dialog.ShowError(fmt.Errorf("WoW executable not found at %s. Ensure your TurtleWoW directory is correct", wowExePath), myWindow)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
205
pkg/launcher/vanilla_tweaks.go
Normal file
205
pkg/launcher/vanilla_tweaks.go
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
package launcher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"turtlesilicon/pkg/paths"
|
||||||
|
"turtlesilicon/pkg/utils"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/dialog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApplyVanillaTweaks applies vanilla-tweaks to WoW.exe to create WoW-tweaked.exe
|
||||||
|
func ApplyVanillaTweaks(myWindow fyne.Window) error {
|
||||||
|
if paths.TurtlewowPath == "" {
|
||||||
|
return fmt.Errorf("TurtleWoW path not set")
|
||||||
|
}
|
||||||
|
if paths.CrossoverPath == "" {
|
||||||
|
return fmt.Errorf("CrossOver path not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current working directory (where the app executable is located)
|
||||||
|
execPath, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get executable path: %v", err)
|
||||||
|
}
|
||||||
|
appDir := filepath.Dir(execPath)
|
||||||
|
|
||||||
|
// Check if we're in development mode
|
||||||
|
vanillaTweaksPath := filepath.Join(appDir, "winerosetta", "vanilla-tweaks.exe")
|
||||||
|
if !utils.PathExists(vanillaTweaksPath) {
|
||||||
|
// Try relative path from current working directory (for development)
|
||||||
|
workingDir, _ := os.Getwd()
|
||||||
|
vanillaTweaksPath = filepath.Join(workingDir, "winerosetta", "vanilla-tweaks.exe")
|
||||||
|
if !utils.PathExists(vanillaTweaksPath) {
|
||||||
|
return fmt.Errorf("vanilla-tweaks.exe not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wowExePath := filepath.Join(paths.TurtlewowPath, "WoW.exe")
|
||||||
|
wineloader2Path := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
|
||||||
|
|
||||||
|
if !utils.PathExists(wowExePath) {
|
||||||
|
return fmt.Errorf("WoW.exe not found at %s", wowExePath)
|
||||||
|
}
|
||||||
|
if !utils.PathExists(wineloader2Path) {
|
||||||
|
return fmt.Errorf("wineloader2 not found at %s", wineloader2Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, copy vanilla-tweaks.exe to the TurtleWoW directory temporarily
|
||||||
|
tempVanillaTweaksPath := filepath.Join(paths.TurtlewowPath, "vanilla-tweaks.exe")
|
||||||
|
|
||||||
|
// Copy vanilla-tweaks.exe to TurtleWoW directory
|
||||||
|
log.Printf("Copying vanilla-tweaks.exe from %s to %s", vanillaTweaksPath, tempVanillaTweaksPath)
|
||||||
|
sourceFile, err := os.Open(vanillaTweaksPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open vanilla-tweaks.exe: %v", err)
|
||||||
|
}
|
||||||
|
defer sourceFile.Close()
|
||||||
|
|
||||||
|
destFile, err := os.Create(tempVanillaTweaksPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create temporary vanilla-tweaks.exe: %v", err)
|
||||||
|
}
|
||||||
|
defer destFile.Close()
|
||||||
|
|
||||||
|
_, err = destFile.ReadFrom(sourceFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to copy vanilla-tweaks.exe: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the copied file is executable
|
||||||
|
if err := os.Chmod(tempVanillaTweaksPath, 0755); err != nil {
|
||||||
|
log.Printf("Warning: failed to set executable permission on vanilla-tweaks.exe: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the command to apply vanilla-tweaks using the correct format:
|
||||||
|
// cd "path" && "wineloader2" ./vanilla-tweaks.exe ./WoW.exe
|
||||||
|
shellCmd := fmt.Sprintf(`cd %s && %s ./vanilla-tweaks.exe ./WoW.exe`,
|
||||||
|
utils.QuotePathForShell(paths.TurtlewowPath),
|
||||||
|
utils.QuotePathForShell(wineloader2Path))
|
||||||
|
|
||||||
|
log.Printf("Applying vanilla-tweaks with command: %s", shellCmd)
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
cmd := exec.Command("sh", "-c", shellCmd)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
|
||||||
|
log.Printf("vanilla-tweaks command output: %s", string(output))
|
||||||
|
|
||||||
|
// Clean up the temporary vanilla-tweaks.exe file
|
||||||
|
if cleanupErr := os.Remove(tempVanillaTweaksPath); cleanupErr != nil {
|
||||||
|
log.Printf("Warning: failed to clean up temporary vanilla-tweaks.exe: %v", cleanupErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always check if the output file was created, regardless of exit code
|
||||||
|
// Some Wine programs report error exit codes even when they succeed
|
||||||
|
foundPath := GetWoWTweakedExecutablePath()
|
||||||
|
if foundPath == "" {
|
||||||
|
// Only report error if no output file was created
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("vanilla-tweaks command failed: %v", err)
|
||||||
|
return fmt.Errorf("failed to apply vanilla-tweaks: %v\nOutput: %s", err, string(output))
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("vanilla-tweaks completed but WoW-tweaked.exe was not created\nOutput: %s", string(output))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found the file but there was an error code, log it as a warning
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("vanilla-tweaks reported error but output file was created: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("vanilla-tweaks applied successfully")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckForVanillaTweaksExecutable checks if vanilla-tweaks.exe exists and is accessible
|
||||||
|
func CheckForVanillaTweaksExecutable() bool {
|
||||||
|
// Get the current working directory (where the app executable is located)
|
||||||
|
execPath, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
appDir := filepath.Dir(execPath)
|
||||||
|
|
||||||
|
// Check if we're in development mode (running from VSCode)
|
||||||
|
vanillaTweaksPath := filepath.Join(appDir, "winerosetta", "vanilla-tweaks.exe")
|
||||||
|
if utils.PathExists(vanillaTweaksPath) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try relative path from current working directory (for development)
|
||||||
|
workingDir, _ := os.Getwd()
|
||||||
|
vanillaTweaksPath = filepath.Join(workingDir, "winerosetta", "vanilla-tweaks.exe")
|
||||||
|
return utils.PathExists(vanillaTweaksPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVanillaTweaksExecutablePath returns the path to vanilla-tweaks.exe if it exists
|
||||||
|
func GetVanillaTweaksExecutablePath() (string, error) {
|
||||||
|
// Get the current working directory (where the app executable is located)
|
||||||
|
execPath, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to get executable path: %v", err)
|
||||||
|
}
|
||||||
|
appDir := filepath.Dir(execPath)
|
||||||
|
|
||||||
|
// Check if we're in development mode (running from VSCode)
|
||||||
|
vanillaTweaksPath := filepath.Join(appDir, "winerosetta", "vanilla-tweaks.exe")
|
||||||
|
if utils.PathExists(vanillaTweaksPath) {
|
||||||
|
return vanillaTweaksPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try relative path from current working directory (for development)
|
||||||
|
workingDir, _ := os.Getwd()
|
||||||
|
vanillaTweaksPath = filepath.Join(workingDir, "winerosetta", "vanilla-tweaks.exe")
|
||||||
|
if utils.PathExists(vanillaTweaksPath) {
|
||||||
|
return vanillaTweaksPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("vanilla-tweaks.exe not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckForWoWTweakedExecutable checks if WoW_tweaked.exe exists in the TurtleWoW directory
|
||||||
|
func CheckForWoWTweakedExecutable() bool {
|
||||||
|
if paths.TurtlewowPath == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
testPath := filepath.Join(paths.TurtlewowPath, "WoW_tweaked.exe")
|
||||||
|
return utils.PathExists(testPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWoWTweakedExecutablePath returns the path to the WoW_tweaked.exe file if it exists
|
||||||
|
func GetWoWTweakedExecutablePath() string {
|
||||||
|
if paths.TurtlewowPath == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
testPath := filepath.Join(paths.TurtlewowPath, "WoW_tweaked.exe")
|
||||||
|
if utils.PathExists(testPath) {
|
||||||
|
return testPath
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleVanillaTweaksRequest handles the case when vanilla-tweaks is enabled but WoW-tweaked.exe doesn't exist
|
||||||
|
func HandleVanillaTweaksRequest(myWindow fyne.Window, callback func()) {
|
||||||
|
dialog.ShowConfirm("Vanilla-tweaks not found",
|
||||||
|
"WoW-tweaked.exe was not found in your TurtleWoW directory.\n\nWould you like TurtleSilicon to automatically apply vanilla-tweaks for you?",
|
||||||
|
func(confirmed bool) {
|
||||||
|
if confirmed {
|
||||||
|
if err := ApplyVanillaTweaks(myWindow); err != nil {
|
||||||
|
dialog.ShowError(fmt.Errorf("failed to apply vanilla-tweaks: %v", err), myWindow)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// After successful patching, execute the callback
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, myWindow)
|
||||||
|
}
|
35
pkg/ui/ui.go
35
pkg/ui/ui.go
@@ -36,6 +36,7 @@ var (
|
|||||||
stopServiceButton *widget.Button
|
stopServiceButton *widget.Button
|
||||||
metalHudCheckbox *widget.Check
|
metalHudCheckbox *widget.Check
|
||||||
showTerminalCheckbox *widget.Check
|
showTerminalCheckbox *widget.Check
|
||||||
|
vanillaTweaksCheckbox *widget.Check
|
||||||
envVarsEntry *widget.Entry
|
envVarsEntry *widget.Entry
|
||||||
pulsingActive = false
|
pulsingActive = false
|
||||||
)
|
)
|
||||||
@@ -277,6 +278,17 @@ func CreateUI(myWindow fyne.Window) fyne.CanvasObject {
|
|||||||
})
|
})
|
||||||
showTerminalCheckbox.SetChecked(prefs.ShowTerminalNormally)
|
showTerminalCheckbox.SetChecked(prefs.ShowTerminalNormally)
|
||||||
|
|
||||||
|
vanillaTweaksCheckbox = widget.NewCheck("Enable vanilla-tweaks", func(checked bool) {
|
||||||
|
launcher.EnableVanillaTweaks = checked
|
||||||
|
// Save to preferences
|
||||||
|
prefs, _ := utils.LoadPrefs()
|
||||||
|
prefs.EnableVanillaTweaks = checked
|
||||||
|
utils.SavePrefs(prefs)
|
||||||
|
log.Printf("Vanilla-tweaks enabled: %v", launcher.EnableVanillaTweaks)
|
||||||
|
})
|
||||||
|
vanillaTweaksCheckbox.SetChecked(prefs.EnableVanillaTweaks)
|
||||||
|
launcher.EnableVanillaTweaks = prefs.EnableVanillaTweaks
|
||||||
|
|
||||||
// Load environment variables from preferences
|
// Load environment variables from preferences
|
||||||
if prefs.EnvironmentVariables != "" {
|
if prefs.EnvironmentVariables != "" {
|
||||||
launcher.CustomEnvVars = prefs.EnvironmentVariables
|
launcher.CustomEnvVars = prefs.EnvironmentVariables
|
||||||
@@ -344,14 +356,14 @@ func CreateUI(myWindow fyne.Window) fyne.CanvasObject {
|
|||||||
UpdateAllStatuses() // Initial UI state update
|
UpdateAllStatuses() // Initial UI state update
|
||||||
|
|
||||||
// Set up periodic status updates to keep service status in sync
|
// Set up periodic status updates to keep service status in sync
|
||||||
go func() {
|
// go func() {
|
||||||
for {
|
// for {
|
||||||
time.Sleep(5 * time.Second) // Check every 5 seconds
|
// time.Sleep(5 * time.Second) // Check every 5 seconds
|
||||||
fyne.DoAndWait(func() {
|
// fyne.DoAndWait(func() {
|
||||||
UpdateAllStatuses()
|
// UpdateAllStatuses()
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}()
|
// }()
|
||||||
|
|
||||||
// Create GitHub link
|
// Create GitHub link
|
||||||
githubURL := "https://github.com/tairasu/TurtleSilicon"
|
githubURL := "https://github.com/tairasu/TurtleSilicon"
|
||||||
@@ -362,13 +374,15 @@ func CreateUI(myWindow fyne.Window) fyne.CanvasObject {
|
|||||||
githubLink := widget.NewHyperlink("GitHub Repository", parsedURL)
|
githubLink := widget.NewHyperlink("GitHub Repository", parsedURL)
|
||||||
githubContainer := container.NewCenter(githubLink)
|
githubContainer := container.NewCenter(githubLink)
|
||||||
|
|
||||||
return container.NewVBox(
|
return container.NewPadded(
|
||||||
|
container.NewVBox(
|
||||||
logoContainer,
|
logoContainer,
|
||||||
pathSelectionForm,
|
pathSelectionForm,
|
||||||
patchOperationsLayout,
|
patchOperationsLayout,
|
||||||
container.NewHBox(
|
container.NewGridWithColumns(3,
|
||||||
metalHudCheckbox,
|
metalHudCheckbox,
|
||||||
showTerminalCheckbox,
|
showTerminalCheckbox,
|
||||||
|
vanillaTweaksCheckbox,
|
||||||
),
|
),
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
widget.NewLabel("Environment Variables:"),
|
widget.NewLabel("Environment Variables:"),
|
||||||
@@ -376,5 +390,6 @@ func CreateUI(myWindow fyne.Window) fyne.CanvasObject {
|
|||||||
container.NewPadded(launchButton),
|
container.NewPadded(launchButton),
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
githubContainer,
|
githubContainer,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ type UserPrefs struct {
|
|||||||
EnvironmentVariables string `json:"environment_variables"`
|
EnvironmentVariables string `json:"environment_variables"`
|
||||||
SaveSudoPassword bool `json:"save_sudo_password"`
|
SaveSudoPassword bool `json:"save_sudo_password"`
|
||||||
ShowTerminalNormally bool `json:"show_terminal_normally"`
|
ShowTerminalNormally bool `json:"show_terminal_normally"`
|
||||||
|
EnableVanillaTweaks bool `json:"enable_vanilla_tweaks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrefsPath() (string, error) {
|
func getPrefsPath() (string, error) {
|
||||||
|
BIN
winerosetta/vanilla-tweaks.exe
Executable file
BIN
winerosetta/vanilla-tweaks.exe
Executable file
Binary file not shown.
Reference in New Issue
Block a user