Skip to content

Commit c687e34

Browse files
committed
fix: fix game launch in windows
1 parent 61481a3 commit c687e34

File tree

2 files changed

+101
-95
lines changed

2 files changed

+101
-95
lines changed

libs/game-state/src/current-game.ts

Lines changed: 100 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -50,119 +50,125 @@ export const baseUrl$ = atom('');
5050

5151
export async function runGame(entry: GameShelfEntry): Promise<void> {
5252
if (!entry) throw new Error('Game not found');
53-
baseUrl$.set(entry.loadConfig.url);
54-
55-
let descriptor: GameDescriptor = entry.loadConfig.descriptor || {
56-
id: entry.id,
57-
mode: entry.mode,
58-
title: entry.title,
59-
file: '',
60-
};
6153
try {
62-
const configContent = await fetchTextContent(baseUrl$.value, 'game.cfg');
63-
const config = parseToml<PlayerConfig>(configContent);
64-
if (config.game?.length === 1) {
65-
[descriptor] = config.game;
66-
} else {
67-
const found = config.game?.find((game) => game.id === entry.id);
68-
if (!found) throw new Error('Config not found');
69-
descriptor = found;
70-
}
71-
} catch (e) {
72-
console.error('Game config not loaded', e);
73-
}
54+
baseUrl$.set(entry.loadConfig.url);
7455

75-
if (descriptor?.mode === 'classic' || !descriptor?.mode) {
56+
let descriptor: GameDescriptor = entry.loadConfig.descriptor || {
57+
id: entry.id,
58+
mode: entry.mode,
59+
title: entry.title,
60+
file: '',
61+
};
7662
try {
77-
const cfgContent = await fetchTextContent(baseUrl$.value, 'qspgui.cfg');
78-
const cfgData = parseCfg(cfgContent);
79-
if (!cfgData || !Object.keys(cfgData).length) throw new Error('Invalid config file');
80-
qspGuiCfg$.set(cfgData);
81-
} catch {
82-
// no-op
63+
const configContent = await fetchTextContent(baseUrl$.value, 'game.cfg');
64+
const config = parseToml<PlayerConfig>(configContent);
65+
if (config.game?.length === 1) {
66+
[descriptor] = config.game;
67+
} else {
68+
const found = config.game?.find((game) => game.id === entry.id);
69+
if (!found) throw new Error('Config not found');
70+
descriptor = found;
71+
}
72+
} catch (e) {
73+
console.error('Game config not loaded', e);
8374
}
84-
}
8575

86-
if (descriptor.mode === 'aero') {
87-
if (descriptor.aero) {
88-
descriptor.window = {
89-
...(descriptor.window ?? {}),
90-
...descriptor.aero,
91-
resizable: false,
92-
};
93-
} else {
76+
if (descriptor?.mode === 'classic' || !descriptor?.mode) {
9477
try {
95-
const content = await fetchTextContent(baseUrl$.value, 'config.xml');
96-
const parser = new DOMParser();
97-
const doc = parser.parseFromString(content, 'application/xml');
98-
const gameElement = doc.querySelector('game');
99-
if (gameElement) {
100-
const width = parseInt(gameElement.getAttribute('width') || '800');
101-
const height = parseInt(gameElement.getAttribute('height') || '600');
78+
const cfgContent = await fetchTextContent(baseUrl$.value, 'qspgui.cfg');
79+
const cfgData = parseCfg(cfgContent);
80+
if (!cfgData || !Object.keys(cfgData).length) throw new Error('Invalid config file');
81+
qspGuiCfg$.set(cfgData);
82+
} catch {
83+
// no-op
84+
}
85+
}
86+
87+
if (descriptor.mode === 'aero') {
88+
if (descriptor.aero) {
89+
descriptor.window = {
90+
...(descriptor.window ?? {}),
91+
...descriptor.aero,
92+
resizable: false,
93+
};
94+
} else {
95+
try {
96+
const content = await fetchTextContent(baseUrl$.value, 'config.xml');
97+
const parser = new DOMParser();
98+
const doc = parser.parseFromString(content, 'application/xml');
99+
const gameElement = doc.querySelector('game');
100+
if (gameElement) {
101+
const width = parseInt(gameElement.getAttribute('width') || '800');
102+
const height = parseInt(gameElement.getAttribute('height') || '600');
103+
descriptor.aero = {
104+
width,
105+
height,
106+
};
107+
descriptor.window = {
108+
...(descriptor.window ?? {}),
109+
width,
110+
height,
111+
resizable: false,
112+
};
113+
}
114+
} catch {
102115
descriptor.aero = {
103-
width,
104-
height,
116+
width: 800,
117+
height: 600,
105118
};
106119
descriptor.window = {
107120
...(descriptor.window ?? {}),
108-
width,
109-
height,
121+
width: 800,
122+
height: 600,
110123
resizable: false,
111124
};
112125
}
113-
} catch {
114-
descriptor.aero = {
115-
width: 800,
116-
height: 600,
117-
};
118-
descriptor.window = {
119-
...(descriptor.window ?? {}),
120-
width: 800,
121-
height: 600,
122-
resizable: false,
123-
};
124126
}
125127
}
126-
}
127128

128-
windowManager.setTitle(entry.title);
129-
setupGlobalHotKeys();
130-
if (descriptor?.hotkeys) {
131-
setupCustomHotKeys(descriptor.hotkeys);
132-
}
133-
if (descriptor?.resources?.icon) {
134-
windowManager.setIcon(baseUrl$.value, descriptor.resources.icon);
135-
}
136-
loadAdditionalResources(descriptor?.resources);
137-
if (descriptor?.themes) {
138-
await registerThemes(descriptor.themes);
139-
}
140-
if (descriptor?.defaultTheme) {
141-
const theme = themeRegistry$.value[descriptor.defaultTheme];
142-
if (theme) {
143-
currentTheme$.set(descriptor.defaultTheme);
129+
windowManager.setTitle(entry.title);
130+
setupGlobalHotKeys();
131+
if (descriptor?.hotkeys) {
132+
setupCustomHotKeys(descriptor.hotkeys);
133+
}
134+
if (descriptor?.resources?.icon) {
135+
windowManager.setIcon(baseUrl$.value, descriptor.resources.icon);
136+
}
137+
loadAdditionalResources(descriptor?.resources);
138+
if (descriptor?.themes) {
139+
await registerThemes(descriptor.themes);
140+
}
141+
if (descriptor?.defaultTheme) {
142+
const theme = themeRegistry$.value[descriptor.defaultTheme];
143+
if (theme) {
144+
currentTheme$.set(descriptor.defaultTheme);
145+
} else {
146+
showNotice(`Theme ${descriptor.defaultTheme} not found`);
147+
}
148+
} else if (descriptor?.mode === 'aero') {
149+
currentTheme$.set(AERO_THEME);
144150
} else {
145-
showNotice(`Theme ${descriptor.defaultTheme} not found`);
151+
currentTheme$.set(CLASSIC_THEME);
146152
}
147-
} else if (descriptor?.mode === 'aero') {
148-
currentTheme$.set(AERO_THEME);
149-
} else {
150-
currentTheme$.set(CLASSIC_THEME);
151-
}
152-
loadThemeTranslations(currentTranslations$.value);
153-
if (descriptor) applyWindowSettings(descriptor.window);
154-
let gameSource = await fetchBinaryContent(baseUrl$.value, entry.loadConfig.entrypoint);
155-
if (!gameSource) throw new Error('Failed to load game');
156-
const isQsps = entry.loadConfig.entrypoint.toLowerCase().endsWith('.qsps');
157-
if (isQsps) {
158-
gameSource = convertQsps(gameSource);
153+
loadThemeTranslations(currentTranslations$.value);
154+
if (descriptor) applyWindowSettings(descriptor.window);
155+
let gameSource = await fetchBinaryContent(baseUrl$.value, entry.loadConfig.entrypoint);
156+
if (!gameSource) throw new Error('Failed to load game');
157+
const isQsps = entry.loadConfig.entrypoint.toLowerCase().endsWith('.qsps');
158+
if (isQsps) {
159+
gameSource = convertQsps(gameSource);
160+
}
161+
qspApi$.value?.openGame(gameSource, true);
162+
qspApi$.value?.restartGame();
163+
currentGameEntry$.set(entry);
164+
if (descriptor) currentGame$.set(descriptor);
165+
loadSaveList();
166+
isPaused$.set(false);
167+
} catch (e) {
168+
console.error(e);
169+
showNotice(e instanceof Error ? e.message : String(e));
170+
stopCurrentGame();
159171
}
160-
qspApi$.value?.openGame(gameSource, true);
161-
qspApi$.value?.restartGame();
162-
currentGameEntry$.set(entry);
163-
if (descriptor) currentGame$.set(descriptor);
164-
loadSaveList();
165-
isPaused$.set(false);
166172
}
167173

168174
let wasResized = false;

src-tauri/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn read_file(path: &Path, check_lowercase: bool) -> Result<Vec<u8>, String> {
6262

6363
#[command]
6464
fn read_resource(url: String, state: State<'_, GamesPath>) -> Result<Vec<u8>, String> {
65-
let uri = url.replace("qsp://", "");
65+
let uri = url.replace("qsp://", "").replace("https://qsp", "");
6666
let path = decode(&uri).unwrap_or_default();
6767
let slash_index = path.chars().position(|c| c == '/').unwrap();
6868
let uuid_str = &path[0..slash_index];

0 commit comments

Comments
 (0)