Skip to content
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

Read addonlist.txt #16

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions shared/addonlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ export interface WriteAddonlistParams {
gameDir: string
data: string
}

export interface ReadAddonlistParams {
steamGamesDir: string
gameDir: string
}
3 changes: 2 additions & 1 deletion shared/bridge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AddonId } from './addon'
import type { WriteAddonlistParams } from './addonlist'
import type { WriteAddonlistParams, ReadAddonlistParams } from './addonlist'
import type { GameManifest, RequestGameManifestParams, UninstallAddonsParams } from './manifest'
import type { User } from './user'
import type { CreateVpkOptions, ExportVpkOptions } from './vpk'
Expand All @@ -15,6 +15,7 @@ export interface BridgeApi {
getPath: () => Promise<string>
getPathJoin: (file: string) => Promise<string>
writeAddonList: (params: WriteAddonlistParams) => Promise<void>
readAddonList: (params: ReadAddonlistParams) => Promise<string[]>
extractVpk: (options: ExportVpkOptions) => Promise<void>
uninstallAddons: (params: UninstallAddonsParams) => Promise<AddonId[]>
createVpk: (options: CreateVpkOptions) => Promise<void>
Expand Down
46 changes: 44 additions & 2 deletions src/main/addonlist.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fs from 'fs'
import { WriteAddonlistParams } from 'shared'
const path = require('path')
import { WriteAddonlistParams, ReadAddonlistParams } from 'shared'
import type { AddonId } from 'shared'
import path from 'path'

export async function writeAddonList(params: WriteAddonlistParams): Promise<boolean> {
console.log('Writing addonlist.txt to disk...')
Expand All @@ -17,3 +18,44 @@ export async function writeAddonList(params: WriteAddonlistParams): Promise<bool
return false
}
}
export async function readAddonList(params: ReadAddonlistParams): Promise<string[] | string> {

console.log('Reading addonlist.txt')
const dir = path.join(params.steamGamesDir, 'common', params.gameDir, '/addonlist.txt')
console.log(dir)

try {
const addonlist = await fs.promises.readFile(dir, 'utf-8')
console.log('File succesfully read')

// Regex to match .vpk files installed from addonlist.txt
const regex = /"([^"]+\.vpk)"\s+"(\d)"/g

//rebundant variable that might be useful for future use
// const result: { txtAddonID: string; txtEnabled: boolean }[] = []

//Store AddonIds that are active in the addonlist
const txtActiveAddon: AddonId[] = []

// Loop through all matches with regex sorcery
let match
while ((match = regex.exec(addonlist)) !== null) {
// Workshop files have a double backward slash replace them to single forward slash
// This is needed to be done because by some reason regex returns double backward slashes

const txtFoundAddonID: string = match[1].replace(/\\/g, '/')
const txtFoundEnabled: boolean = parseInt(match[2], 2) === 1

if (txtFoundEnabled) {
// Add to enabled addons array that were found in the text file
txtActiveAddon.push(txtFoundAddonID);
}
}

return txtActiveAddon
} catch (error){
console.error(error);
// Send empty array, to avoid getting softlocked in case of an error
return []
}
}
8 changes: 6 additions & 2 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {
RequestGameManifestParams,
UninstallAddonsParams,
User,
WriteAddonlistParams
WriteAddonlistParams,
ReadAddonlistParams
} from 'shared'
import icon from '../../resources/icon.png?asset'
import { writeAddonList } from './addonlist'
import { writeAddonList, readAddonList } from './addonlist'
import { requestGameManifest } from './manifest'
import { openDirectory, openWorkingDirectory, readUserFile, writeUserFile } from './user'
import { createVpk, extractVpk, uninstallAddons } from './vpk'
Expand All @@ -27,6 +28,9 @@ ipcMain.handle('requestGameManifest', async (_e, params: RequestGameManifestPara
ipcMain.handle('addonlist:write', async (_e, params: WriteAddonlistParams) => {
return writeAddonList(params)
})
ipcMain.handle('addonlist:read', async (_e, params: ReadAddonlistParams) => {
return await readAddonList(params);
});

ipcMain.handle('profile:write', async (_e, profileData: User) => writeUserFile(profileData))
ipcMain.handle('profile:read', async () => readUserFile())
Expand Down
2 changes: 2 additions & 0 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
RequestGameManifestParams,
User,
WriteAddonlistParams,
ReadAddonlistParams,
ExportVpkOptions,
UninstallAddonsParams,
CreateVpkOptions
Expand All @@ -15,6 +16,7 @@ const api: BridgeApi = {
requestGameManifest: (params: RequestGameManifestParams) =>
ipcRenderer.invoke('requestGameManifest', params),
writeAddonList: (params: WriteAddonlistParams) => ipcRenderer.invoke('addonlist:write', params),
readAddonList: (params: ReadAddonlistParams) => ipcRenderer.invoke('addonlist:read', params),
openLinkInBrowser: (url: string) => openLinkInBrowser(url),
writeUserFile: (profileData: User) => ipcRenderer.invoke('profile:write', profileData),
readUserFile: () => ipcRenderer.invoke('profile:read'),
Expand Down
13 changes: 13 additions & 0 deletions src/renderer/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,20 @@ export async function writeAddonList(): Promise<void> {
data: outputVdfString
})
}
export async function readAddonList() {
const user = get(userStore)

const enabledAddonIds = await window.api.readAddonList({
steamGamesDir: user.steamGamesDir,
gameDir: `${games[550].rootDirectoryName}/${games[550].gameDirectory}`
})
try {
// Update DB with the addonlist
activeProfileStore.addonListEnabled(enabledAddonIds)
} catch (error) {
console.error('Failed to read addon list:', error);
}
}
export async function extractVpk(params: ExportVpkOptions) {
window.api.extractVpk(params)
}
Expand Down
5 changes: 2 additions & 3 deletions src/renderer/src/components/navigation/SettingsModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import { X } from 'lucide-svelte'
import { userStore } from '../../stores/user'
import SteamGamesDirectoryManager from '../SteamGamesDirectoryManager.svelte'
import { writeAddonList } from '../../api/api'

import { writeAddonList, readAddonList } from '../../api/api'
function close() {
modalStore.close()
}
Expand All @@ -16,7 +15,6 @@
function openWorkingDir() {
window.api.openWorkingDirectory()
}

let tabSet: 'game dir' | 'dev' | 'networking' = 'game dir'
</script>

Expand Down Expand Up @@ -44,6 +42,7 @@
<button class="btn variant-filled" on:click={userStore.resetFirstTimeSetup}
>reset first time setup</button
>
<button class="btn variant-filled" on:click={readAddonList}>read addonlist</button>
<button class="btn variant-filled" on:click={writeAddonList}>write addonlist</button>
</div>
{:else if tabSet === 'networking'}
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/src/stores/active-profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ function createProfileStore() {
}
}

function addonListEnabled(addonIds: string[]) {
db.profiles.update(get(store).id, {
enabledAddonIds: addonIds
})
}

function toggleAddonEnabled(addonId: string) {
const list = get(store).enabledAddonIds
if (list.includes(addonId)) {
Expand Down Expand Up @@ -66,6 +72,7 @@ function createProfileStore() {
deleteProfile,
renameProfile,
toggleAddonEnabled,
addonListEnabled,
toggleShuffleEnabled
}
}
Expand Down