Skip to content

Commit

Permalink
[Feat-macOS] Download GPTK from Wine Manager (#3868)
Browse files Browse the repository at this point in the history
* [Feat-macOS] Download GPTK from Wine Manager

* feat: auto update Wine Selector on new version download

* fix: tests

* feat: Update function names for Game Porting Toolkit

* Update src/frontend/screens/Settings/components/WineVersionSelector.tsx

Co-authored-by: Mathis Dröge <mathis.droege@ewe.net>

* chore: pr comments

---------

Co-authored-by: Flavio F Lima <flavioislima@users.noreply.github.com>
Co-authored-by: Mathis Dröge <mathis.droege@ewe.net>
  • Loading branch information
3 people authored Jul 26, 2024
1 parent b51a319 commit cb42c8c
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 28 deletions.
9 changes: 6 additions & 3 deletions src/backend/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import { logError, logInfo, LogPrefix } from './logger/logger'
import {
getCrossover,
getDefaultWine,
getGamingPortingToolkitWine,
getGamePortingToolkitWine,
getLinuxWineSet,
getSystemGamePortingToolkitWine,
getWhisky,
getWineOnMac,
getWineskinWine
Expand Down Expand Up @@ -134,14 +135,16 @@ abstract class GlobalConfig {
return new Set<WineInstallation>()
}

const getGPTKWine = await getGamePortingToolkitWine()
const getSystemGPTK = await getSystemGamePortingToolkitWine()
const crossover = await getCrossover()
const wineOnMac = await getWineOnMac()
const wineskinWine = await getWineskinWine()
const gamingPortingToolkitWine = await getGamingPortingToolkitWine()
const whiskyWine = await getWhisky()

return new Set([
...gamingPortingToolkitWine,
...getGPTKWine,
...getSystemGPTK,
...crossover,
...wineOnMac,
...wineskinWine,
Expand Down
2 changes: 1 addition & 1 deletion src/backend/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ export async function downloadDefaultWine() {
!version.version.endsWith('-LoL')
)
} else if (isMac) {
return version.version.includes('Wine-Crossover')
return version.version.includes('Game-Porting-Toolkit')
}
return false
})[0]
Expand Down
69 changes: 60 additions & 9 deletions src/backend/utils/compatibility_layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,62 @@ export async function getCrossover(): Promise<Set<WineInstallation>> {
* Detects Gaming Porting Toolkit Wine installs on Mac
* @returns Promise<Set<WineInstallation>>
**/
export async function getGamingPortingToolkitWine(): Promise<
export async function getGamePortingToolkitWine(): Promise<
Set<WineInstallation>
> {
const gamingPortingToolkitWine = new Set<WineInstallation>()
const gamePortingToolkitWine = new Set<WineInstallation>()
if (!isMac) {
return gamingPortingToolkitWine
return gamePortingToolkitWine
}

const GPTK_ToolPath = join(toolsPath, 'game-porting-toolkit')
const wineGPTKPaths = new Set<string>()

if (existsSync(GPTK_ToolPath)) {
readdirSync(GPTK_ToolPath).forEach((path) => {
wineGPTKPaths.add(join(GPTK_ToolPath, path))
})
}

wineGPTKPaths.forEach((winePath) => {
const infoFilePath = join(winePath, 'Contents/Info.plist')
if (existsSync(infoFilePath)) {
const wineBin = join(winePath, '/Contents/Resources/wine/bin/wine64')
try {
const name = winePath.split('/').pop() || ''
if (existsSync(wineBin)) {
gamePortingToolkitWine.add({
...getWineExecs(wineBin),
lib: `${winePath}/Contents/Resources/wine/lib`,
lib32: `${winePath}/Contents/Resources/wine/lib`,
bin: wineBin,
name,
type: 'toolkit',
...getWineExecs(wineBin)
})
}
} catch (error) {
logError(
`Error getting wine version for GPTK ${wineBin}`,
LogPrefix.GlobalConfig
)
}
}
})

return gamePortingToolkitWine
}

/**
* Detects Gaming Porting Toolkit Wine installs on Mac
* @returns Promise<Set<WineInstallation>>
**/
export async function getSystemGamePortingToolkitWine(): Promise<
Set<WineInstallation>
> {
const systemGPTK = new Set<WineInstallation>()
if (!isMac) {
return systemGPTK
}

logInfo('Searching for Gaming Porting Toolkit Wine', LogPrefix.GlobalConfig)
Expand All @@ -350,18 +400,19 @@ export async function getGamingPortingToolkitWine(): Promise<

if (existsSync(wineBin)) {
logInfo(
`Found Gaming Porting Toolkit Wine at ${dirname(wineBin)}`,
`Found Game Porting Toolkit Wine at ${dirname(wineBin)}`,
LogPrefix.GlobalConfig
)
try {
const { stdout: out } = await execAsync(`'${wineBin}' --version`)
const version = out.split('\n')[0]
gamingPortingToolkitWine.add({
const GPTKDIR = join(dirname(wineBin), '..')
systemGPTK.add({
...getWineExecs(wineBin),
name: `GPTK Wine (DX11/DX12 Only) - ${version}`,
name: `GPTK System (DX11/DX12 Only) - ${version}`,
type: 'toolkit',
lib: `${dirname(wineBin)}/../lib`,
lib32: `${dirname(wineBin)}/../lib`,
lib: join(GPTKDIR, 'lib'),
lib32: join(GPTKDIR, 'lib'),
bin: wineBin
})
} catch (error) {
Expand All @@ -372,7 +423,7 @@ export async function getGamingPortingToolkitWine(): Promise<
}
}

return gamingPortingToolkitWine
return systemGPTK
}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/backend/wine/manager/downloader/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ export const WINECROSSOVER_URL =
/// Url to Wine Staging for macOS github release page
export const WINESTAGINGMACOS_URL =
'https://api.github.com/repos/Gcenx/macOS_Wine_builds/releases'

/// Url to Game Porting Toolkit from Gcenx github release page
export const GPTK_URL =
'https://api.github.com/repos/Gcenx/game-porting-toolkit/releases'
17 changes: 16 additions & 1 deletion src/backend/wine/manager/downloader/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
PROTON_URL,
WINELUTRIS_URL,
WINECROSSOVER_URL,
WINESTAGINGMACOS_URL
WINESTAGINGMACOS_URL,
GPTK_URL
} from './constants'
import { VersionInfo, Repositorys } from 'common/types'
import {
Expand Down Expand Up @@ -134,6 +135,20 @@ async function getAvailableVersions({
})
break
}
case Repositorys.GPTK: {
await fetchReleases({
url: GPTK_URL,
type: 'Game-Porting-Toolkit',
count: count
})
.then((fetchedReleases: VersionInfo[]) => {
releases.push(...fetchedReleases)
})
.catch((error: Error) => {
logError(error, LogPrefix.WineDownloader)
})
break
}
default: {
logWarning(
`Unknown and not supported repository key passed! Skip fetch for ${repo}`,
Expand Down
14 changes: 11 additions & 3 deletions src/backend/wine/manager/downloader/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ interface fetchProps {
count: number
}

function getVersionName(type: string, tag_name: string): string {
if (type.includes('Wine')) {
return `Wine-${tag_name}`
} else if (type.includes('Toolkit')) {
return `${tag_name}`
} else {
return `Proton-${tag_name}`
}
}

/**
* Helper to fetch releases from given url.
*
Expand All @@ -32,9 +42,7 @@ async function fetchReleases({
.then((data) => {
for (const release of data.data) {
const release_data = {} as VersionInfo
release_data.version = type.includes('Wine')
? `Wine-${release.tag_name}`
: `Proton-${release.tag_name}`
release_data.version = getVersionName(type, release.tag_name)
release_data.type = type
release_data.date = release.published_at.split('T')[0]
release_data.disksize = 0
Expand Down
24 changes: 20 additions & 4 deletions src/backend/wine/manager/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ async function updateWineVersionInfos(
logInfo('Fetching upstream information...', LogPrefix.WineDownloader)

const repositorys = isMac
? [Repositorys.WINECROSSOVER, Repositorys.WINESTAGINGMACOS]
? [
Repositorys.WINECROSSOVER,
Repositorys.WINESTAGINGMACOS,
Repositorys.GPTK
]
: [Repositorys.WINEGE, Repositorys.PROTONGE]

await getAvailableVersions({
Expand Down Expand Up @@ -86,6 +90,16 @@ async function updateWineVersionInfos(
return releases
}

function getInstallDir(release: WineVersionInfo): string {
if (release?.type?.includes('Wine')) {
return `${toolsPath}/wine`
} else if (release.type.includes('Toolkit')) {
return `${toolsPath}/game-porting-toolkit`
} else {
return `${toolsPath}/proton`
}
}

async function installWineVersion(
release: WineVersionInfo,
onProgress: (status: WineManagerStatus) => void
Expand All @@ -97,6 +111,10 @@ async function installWineVersion(
mkdirSync(`${toolsPath}/wine`, { recursive: true })
}

if (isMac && !existsSync(`${toolsPath}/game-porting-toolkit`)) {
mkdirSync(`${toolsPath}/game-porting-toolkit`, { recursive: true })
}

if (!existsSync(`${toolsPath}/proton`)) {
mkdirSync(`${toolsPath}/proton`, { recursive: true })
}
Expand All @@ -106,9 +124,7 @@ async function installWineVersion(
LogPrefix.WineDownloader
)

const installDir = release?.type?.includes('Wine')
? `${toolsPath}/wine`
: `${toolsPath}/proton`
const installDir = getInstallDir(release)

const abortController = createAbortController(release.version)

Expand Down
4 changes: 3 additions & 1 deletion src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ export type Type =
| 'Wine-Kron4ek'
| 'Wine-Crossover'
| 'Wine-Staging-macOS'
| 'Game-Porting-Toolkit'

/**
* Interface contains information about a version
Expand Down Expand Up @@ -713,7 +714,8 @@ export enum Repositorys {
PROTON,
WINELUTRIS,
WINECROSSOVER,
WINESTAGINGMACOS
WINESTAGINGMACOS,
GPTK
}

export type WineManagerStatus =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function WineVersionSelector() {
setRefreshing(false)
}
getAltWine()
return window.api.handleWineVersionsUpdated(getAltWine)
}, [])

useEffect(() => {
Expand Down
12 changes: 6 additions & 6 deletions src/frontend/screens/WineManager/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,22 @@ export default function WineManager(): JSX.Element | null {
value: 'winege',
enabled: isLinux
}
const winecrossover: WineManagerUISettings = {
type: 'Wine-Crossover',
value: 'winecrossover',
const gamePortingToolkit: WineManagerUISettings = {
type: 'Game-Porting-Toolkit',
value: 'gpt',
enabled: !isLinux
}

const [repository, setRepository] = useState<WineManagerUISettings>(
isLinux ? winege : winecrossover
isLinux ? winege : gamePortingToolkit
)
const [wineManagerSettings, setWineManagerSettings] = useState<
WineManagerUISettings[]
>([
{ type: 'Wine-GE', value: 'winege', enabled: isLinux },
{ type: 'Proton-GE', value: 'protonge', enabled: isLinux },
{ type: 'Wine-Crossover', value: 'winecrossover', enabled: !isLinux },
{ type: 'Wine-Staging-macOS', value: 'winestagingmacos', enabled: !isLinux }
{ type: 'Game-Porting-Toolkit', value: 'gpt', enabled: !isLinux },
{ type: 'Wine-Crossover', value: 'winecrossover', enabled: !isLinux }
])

const getWineVersions = (repo: Type) => {
Expand Down

0 comments on commit cb42c8c

Please sign in to comment.