Files
VRCX/src/stores/launch.js
2026-01-11 06:05:10 +13:00

189 lines
5.6 KiB
JavaScript

import { nextTick, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { instanceRequest } from '../api';
import { parseLocation } from '../shared/utils';
import { watchState } from '../service/watchState';
import configRepository from '../service/config';
export const useLaunchStore = defineStore('Launch', () => {
const isLaunchOptionsDialogVisible = ref(false);
const isOpeningInstance = ref(false);
const launchDialogData = ref({
visible: false,
loading: false,
tag: '',
shortName: ''
});
watch(
() => watchState.isLoggedIn,
() => {
isLaunchOptionsDialogVisible.value = false;
},
{ flush: 'sync' }
);
function showLaunchOptions() {
isLaunchOptionsDialogVisible.value = true;
}
/**
*
* @param {string} tag
* @param {string} shortName
* @returns {Promise<void>}
*/
async function showLaunchDialog(tag, shortName = null) {
launchDialogData.value = {
visible: true,
// flag, use for trigger adjustDialogZ
loading: true,
tag,
shortName
};
nextTick(() => (launchDialogData.value.loading = false));
}
/**
*
* @param {string} location
* @param {string} shortName
* @returns {Promise<string>} launchUrl
*/
async function getLaunchUrl(location, shortName) {
const L = parseLocation(location);
if (
shortName &&
L.instanceType !== 'public' &&
L.groupAccessType !== 'public'
) {
return `vrchat://launch?ref=vrcx.app&id=${location}&shortName=${shortName}`;
}
// fetch shortName
let newShortName = '';
const response = await instanceRequest.getInstanceShortName({
worldId: L.worldId,
instanceId: L.instanceId
});
if (response.json) {
if (response.json.shortName) {
newShortName = response.json.shortName;
} else {
newShortName = response.json.secureName;
}
}
if (newShortName) {
return `vrchat://launch?ref=vrcx.app&id=${location}&shortName=${newShortName}`;
}
return `vrchat://launch?ref=vrcx.app&id=${location}`;
}
/**
* launch.exe &attach=1
* @param {string} location
* @param {string} shortName
* @returns {Promise<void>}
*/
async function tryOpenInstanceInVrc(location, shortName) {
if (isOpeningInstance.value) {
return;
}
isOpeningInstance.value = true;
let launchUrl = '';
let result = false;
try {
launchUrl = await getLaunchUrl(location, shortName);
result = await AppApi.TryOpenInstanceInVrc(launchUrl);
} catch (e) {
console.error(e);
}
console.log('Attach Game', launchUrl, result);
if (!result) {
toast.warning(
'Failed open instance in VRChat, falling back to self invite'
);
// self invite fallback
try {
const L = parseLocation(location);
await instanceRequest.selfInvite({
instanceId: L.instanceId,
worldId: L.worldId,
shortName
});
toast.success('Self invite sent');
} catch (e) {
console.error(e);
}
}
setTimeout(() => {
isOpeningInstance.value = false;
}, 1000);
}
/**
*
* @param {string} location
* @param {string} shortName
* @param {boolean} desktopMode
* @returns {Promise<void>}
*/
async function launchGame(location, shortName, desktopMode) {
const launchUrl = await getLaunchUrl(location, shortName);
const args = [launchUrl];
const launchArguments =
await configRepository.getString('launchArguments');
const vrcLaunchPathOverride = await configRepository.getString(
'vrcLaunchPathOverride'
);
if (launchArguments) {
args.push(launchArguments);
}
if (desktopMode) {
args.push('--no-vr');
}
try {
if (vrcLaunchPathOverride && !LINUX) {
const result = await AppApi.StartGameFromPath(
vrcLaunchPathOverride,
args.join(' ')
);
if (!result) {
toast.error(
'Failed to launch VRChat, invalid custom path set'
);
} else {
toast.success('VRChat launched');
}
} else {
const result = await AppApi.StartGame(args.join(' '));
if (!result) {
toast.error(
'Failed to find VRChat, set a custom path in launch options'
);
} else {
toast.success('VRChat launched');
}
}
} catch (e) {
console.error(e);
toast.error(`Failed to launch VRChat: ${e.message}`);
}
console.log('Launch Game', args.join(' '), desktopMode);
}
return {
isLaunchOptionsDialogVisible,
isOpeningInstance,
launchDialogData,
showLaunchOptions,
showLaunchDialog,
getLaunchUrl,
launchGame,
tryOpenInstanceInVrc
};
});