Skip to content

comet support #3727

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ win:
- build/bin/win32/legendary.exe
- build/bin/win32/gogdl.exe
- build/bin/win32/nile.exe
- build/bin/win32/comet.exe
files: build/bin/win32/*

portable:
Expand All @@ -50,6 +51,7 @@ mac:
- build/bin/darwin/legendary
- build/bin/darwin/gogdl
- build/bin/darwin/nile
- build/bin/darwin/comet
files:
- build/bin/darwin/*

Expand Down Expand Up @@ -79,6 +81,7 @@ linux:
- build/bin/linux/gogdl
- build/bin/linux/nile
- build/bin/linux/vulkan-helper
- build/bin/linux/comet
files:
- build/bin/linux/*

Expand Down
Binary file added public/bin/darwin/comet
Binary file not shown.
Binary file added public/bin/linux/comet
Binary file not shown.
Binary file added public/bin/win32/comet.exe
Binary file not shown.
1 change: 1 addition & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@
"warning": "Cloud Saves feature is in Beta, please backup your saves before syncing (in case something goes wrong)"
},
"systemInformation": {
"cometVersion": "Comet: {{cometVersion}}",
"copyToClipboard": "Copy to clipboard",
"cpu": "CPU:",
"cpuDescription": "{{numOfCores}}x {{modelName}}",
Expand Down
1 change: 1 addition & 0 deletions src/backend/api/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const setSetting = (args: {
export const getLegendaryVersion = async () =>
ipcRenderer.invoke('getLegendaryVersion')
export const getGogdlVersion = async () => ipcRenderer.invoke('getGogdlVersion')
export const getCometVersion = async () => ipcRenderer.invoke('getCometVersion')
export const getNileVersion = async () => ipcRenderer.invoke('getNileVersion')
export const getEosOverlayStatus = async () =>
ipcRenderer.invoke('getEosOverlayStatus')
Expand Down
11 changes: 11 additions & 0 deletions src/backend/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { GameConfig } from './game_config'
import { GlobalConfig } from './config'
import { LegendaryUser } from 'backend/storeManagers/legendary/user'
import { GOGUser } from './storeManagers/gog/user'
import gogPresence from './storeManagers/gog/presence'
import { NileUser } from './storeManagers/nile/user'
import {
clearCache,
Expand Down Expand Up @@ -359,6 +360,7 @@ if (!gotTheLock) {
prefix: LogPrefix.Backend
})
}
runOnceWhenOnline(gogPresence.setPresence)
await i18next.use(Backend).init({
backend: {
addPath: path.join(publicDir, 'locales', '{{lng}}', '{{ns}}'),
Expand Down Expand Up @@ -1049,6 +1051,11 @@ ipcMain.handle(
skipVersionCheck
)

if (runner === 'gog') {
gogPresence.setCurrentGame(appName)
await gogPresence.setPresence()
}

const launchResult = await command
.catch((exception) => {
logError(exception, LogPrefix.Backend)
Expand All @@ -1064,6 +1071,10 @@ ipcMain.handle(
stopLogger(appName)
})

if (runner === 'gog') {
gogPresence.setCurrentGame('')
await gogPresence.setPresence()
}
// Stop display sleep blocker
if (powerDisplayId !== null) {
logInfo('Stopping Display Power Saver Blocker', LogPrefix.Backend)
Expand Down
35 changes: 29 additions & 6 deletions src/backend/storeManagers/gog/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
shutdownWine,
sendProgressUpdate,
sendGameStatusUpdate,
getPathDiskSize
getPathDiskSize,
getCometBin
} from '../../utils'
import {
ExtraInfo,
Expand Down Expand Up @@ -55,6 +56,7 @@ import {
} from './electronStores'
import {
appendGamePlayLog,
appendRunnerLog,
appendWinetricksGamePlayLog,
logDebug,
logError,
Expand Down Expand Up @@ -101,6 +103,7 @@ import { readdir, readFile } from 'fs/promises'
import { statSync } from 'fs'
import ini from 'ini'
import { getRequiredRedistList, updateRedist } from './redist'
import { spawn } from 'child_process'

export async function getExtraInfo(appName: string): Promise<ExtraInfo> {
const gameInfo = getGameInfo(appName)
Expand Down Expand Up @@ -667,13 +670,28 @@ export async function launch(
)
appendGamePlayLog(gameInfo, `Launch Command: ${fullCommand}\n\nGame Log:\n`)

const userData: UserData | undefined = configStore.get_nodefault('userData')

sendGameStatusUpdate({ appName, runner: 'gog', status: 'playing' })

sendGameStatusUpdate({
appName,
runner: 'gog',
status: 'playing'
})
let child = undefined

if (userData && userData.username) {
const path = getCometBin()
child = spawn(join(path.dir, path.bin), [
'--from-heroic',
'--username',
userData.username,
'--quit'
])
child.stdout.on('data', (data) => {
appendRunnerLog('gog', data.toString())
})
child.stderr.on('data', (data) => {
appendRunnerLog('gog', data.toString())
})
logInfo(`Launching Comet!`, LogPrefix.Gog)
}

const { error, abort } = await runGogdlCommand(commandParts, {
abortId: appName,
Expand All @@ -685,6 +703,11 @@ export async function launch(
}
})

if (child) {
logInfo(`Killing Comet!`, LogPrefix.Gog)
child.kill()
}

if (abort) {
return true
}
Expand Down
81 changes: 81 additions & 0 deletions src/backend/storeManagers/gog/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { app } from 'electron'
import { logError, logInfo, LogPrefix } from 'backend/logger/logger'
import { axiosClient } from 'backend/utils'
import { GOGUser } from './user'
import { isOnline } from 'backend/online_monitor'

interface PresencePayload {
application_type: string
force_update: boolean
presence: 'online' | 'offline'
version: string
game_id?: string
}

let CURRENT_GAME = ''
let interval: NodeJS.Timeout

function setCurrentGame(game: string) {
CURRENT_GAME = game
}

async function setPresence() {
try {
if (!GOGUser.isLoggedIn() || !isOnline) return
const credentials = await GOGUser.getCredentials()
if (!credentials) return

if (!interval) {
interval = setInterval(setPresence, 5 * 60 * 1000)
}

const payload: PresencePayload = {
application_type: 'Heroic Games Launcher',
force_update: false,
presence: 'online',
version: app.getVersion(),
game_id: undefined
}

if (CURRENT_GAME !== '') {
payload.game_id = CURRENT_GAME
}

const response = await axiosClient.post(
`https://presence.gog.com/users/${credentials.user_id}/status`,
payload,
{ headers: { Authorization: `Bearer ${credentials.access_token}` } }
)
if (response.status === 204) {
logInfo('GOG presence set', LogPrefix.Gog)
}
} catch (e) {
logError(['Failed to set gog presence', e], LogPrefix.Gog)
}
}

async function deletePresence() {
try {
if (!GOGUser.isLoggedIn() || !isOnline) return
const credentials = await GOGUser.getCredentials()
if (!credentials) {
return
}
clearInterval(interval)
const response = await axiosClient.delete(
`https://presence.gog.com/users/${credentials.user_id}/status`,
{ headers: { Authorization: `Bearer ${credentials.access_token}` } }
)
if (response.status === 204) {
logInfo('GOG presence deleted', LogPrefix.Gog)
}
} catch (e) {
logError(['Failed to delete gog presence', e], LogPrefix.Gog)
}
}

export default {
setCurrentGame,
setPresence,
deletePresence
}
14 changes: 14 additions & 0 deletions src/backend/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
installInfoStore as GOGinstallInfoStore,
libraryStore as GOGlibraryStore
} from './storeManagers/gog/electronStores'
import gogPresence from './storeManagers/gog/presence'
import {
installStore as nileInstallStore,
libraryStore as nileLibraryStore
Expand Down Expand Up @@ -239,6 +240,8 @@ async function handleExit() {
const isLocked = existsSync(join(gamesConfigPath, 'lock'))
const mainWindow = getMainWindow()

await gogPresence.deletePresence()

if (isLocked && mainWindow) {
const { response } = await showMessageBox(mainWindow, {
buttons: [i18next.t('box.no'), i18next.t('box.yes')],
Expand Down Expand Up @@ -463,6 +466,16 @@ function getGOGdlBin(): { dir: string; bin: string } {
)
}

function getCometBin(): { dir: string; bin: string } {
const settings = GlobalConfig.get().getSettings()
if (settings?.altCometBin) {
return splitPathAndName(settings.altCometBin)
}
return splitPathAndName(
fixAsarPath(join(publicDir, 'bin', process.platform, 'comet'))
)
}

function getNileBin(): { dir: string; bin: string } {
const settings = GlobalConfig.get().getSettings()
if (settings?.altNileBin) {
Expand Down Expand Up @@ -1521,6 +1534,7 @@ export {
resetHeroic,
getLegendaryBin,
getGOGdlBin,
getCometBin,
getNileBin,
formatEpicStoreUrl,
getSteamRuntime,
Expand Down
14 changes: 13 additions & 1 deletion src/backend/utils/helperBinaries/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { runRunnerCommand as runLegendaryCommand } from '../../storeManagers/legendary/library'
import { runRunnerCommand as runGogdlCommand } from '../../storeManagers/gog/library'
import { runRunnerCommand as runNileCommand } from '../../storeManagers/nile/library'
import { spawnSync } from 'node:child_process'
import { getCometBin } from 'backend/utils'
import { join } from 'path'

async function getLegendaryVersion(): Promise<string> {
const { stdout, error, abort } = await runLegendaryCommand(
Expand Down Expand Up @@ -35,6 +38,15 @@ async function getGogdlVersion(): Promise<string> {
return stdout
}

async function getCometVersion(): Promise<string> {
const path = getCometBin()
const { stdout, error } = spawnSync(join(path.dir, path.bin), ['--version'])

if (error) return 'invalid'

return stdout.toString()
}

async function getNileVersion(): Promise<string> {
const { stdout, error } = await runNileCommand(['--version'], {
abortId: 'nile-version'
Expand All @@ -45,4 +57,4 @@ async function getNileVersion(): Promise<string> {
return stdout
}

export { getLegendaryVersion, getGogdlVersion, getNileVersion }
export { getLegendaryVersion, getGogdlVersion, getNileVersion, getCometVersion }
2 changes: 2 additions & 0 deletions src/backend/utils/ipc_handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { clipboard, ipcMain } from 'electron'
import { callAbortController } from './aborthandler/aborthandler'
import {
getCometVersion,
getGogdlVersion,
getLegendaryVersion,
getNileVersion
Expand All @@ -13,6 +14,7 @@ ipcMain.on('abort', async (event, id) => {
})
ipcMain.handle('getLegendaryVersion', getLegendaryVersion)
ipcMain.handle('getGogdlVersion', getGogdlVersion)
ipcMain.handle('getCometVersion', getCometVersion)
ipcMain.handle('getNileVersion', getNileVersion)
ipcMain.handle('getSystemInfo', async (e, cache) => getSystemInfo(cache))
ipcMain.on('copySystemInfoToClipboard', async () =>
Expand Down
16 changes: 11 additions & 5 deletions src/backend/utils/systeminfo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getOsInfo } from './osInfo'
import { getSteamDeckInfo, type SteamDeckInfo } from './steamDeck'
import { getHeroicVersion } from './heroicVersion'
import {
getCometVersion,
getGogdlVersion,
getLegendaryVersion,
getNileVersion
Expand Down Expand Up @@ -58,6 +59,7 @@ interface SystemInformation {
heroicVersion: string
legendaryVersion: string
gogdlVersion: string
cometVersion: string
nileVersion: string
}
}
Expand All @@ -76,11 +78,13 @@ async function getSystemInfo(cache = true): Promise<SystemInformation> {
const gpus = await getGpuInfo()
const detailedOsInfo = await getOsInfo()
const deckInfo = getSteamDeckInfo(cpus, gpus)
const [legendaryVersion, gogdlVersion, nileVersion] = await Promise.all([
getLegendaryVersion(),
getGogdlVersion(),
getNileVersion()
])
const [legendaryVersion, gogdlVersion, cometVersion, nileVersion] =
await Promise.all([
getLegendaryVersion(),
getGogdlVersion(),
getCometVersion(),
getNileVersion()
])

const sysinfo: SystemInformation = {
CPU: {
Expand All @@ -107,6 +111,7 @@ async function getSystemInfo(cache = true): Promise<SystemInformation> {
heroicVersion: getHeroicVersion(),
legendaryVersion: legendaryVersion,
gogdlVersion: gogdlVersion,
cometVersion: cometVersion,
nileVersion: nileVersion
}
}
Expand Down Expand Up @@ -137,6 +142,7 @@ Software Versions:
Heroic: ${info.softwareInUse.heroicVersion}
Legendary: ${info.softwareInUse.legendaryVersion}
gogdl: ${info.softwareInUse.gogdlVersion}
comet: ${info.softwareInUse.cometVersion}
Nile: ${info.softwareInUse.nileVersion}`
}

Expand Down
1 change: 1 addition & 0 deletions src/common/typedefs/ipcBridge.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ interface AsyncIPCFunctions {
getHeroicVersion: () => string
getLegendaryVersion: () => Promise<string>
getGogdlVersion: () => Promise<string>
getCometVersion: () => Promise<string>
getNileVersion: () => Promise<string>
isFullscreen: () => boolean
isFrameless: () => boolean
Expand Down
1 change: 1 addition & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface AppSettings extends GameSettings {
addStartMenuShortcuts: boolean
addSteamShortcuts: boolean
altGogdlBin: string
altCometBin: string
altLegendaryBin: string
altNileBin: string
autoUpdateGames: boolean
Expand Down
Loading
Loading