Files
VRCX/src/stores/game.js
T
pa f4f78bb5ec refactor: app.js (#1291)
* refactor: frontend

* Fix avatar gallery sort

* Update .NET dependencies

* Update npm dependencies

electron v37.1.0

* bulkRefreshFriends

* fix dark theme

* Remove crowdin

* Fix config.json dialog not updating

* VRCX log file fixes & add Cef log

* Remove SharedVariable, fix startup

* Revert init theme change

* Logging date not working? Fix WinformThemer designer error

* Add Cef request hander, no more escaping main page

* clean

* fix

* fix

* clean

* uh

* Apply thememode at startup, fixes random user colours

* Split database into files

* Instance info remove empty lines

* Open external VRC links with VRCX

* Electron fixes

* fix userdialog style

* ohhhh

* fix store

* fix store

* fix: load all group members after kicking a user

* fix: world dialog favorite button style

* fix: Clear VRCX Cache Timer input value

* clean

* Fix VR overlay

* Fix VR overlay 2

* Fix Discord discord rich presence for RPC worlds

* Clean up age verified user tags

* Fix playerList being occupied after program reload

* no `this`

* Fix login stuck loading

* writable: false

* Hide dialogs on logout

* add flush sync option

* rm LOGIN event

* rm LOGOUT event

* remove duplicate event listeners

* remove duplicate event listeners

* clean

* remove duplicate event listeners

* clean

* fix theme style

* fix t

* clearable

* clean

* fix ipcEvent

* Small changes

* Popcorn Palace support

* Remove checkActiveFriends

* Clean up

* Fix dragEnterCef

* Block API requests when not logged in

* Clear state on login & logout

* Fix worldDialog instances not updating

* use <script setup>

* Fix avatar change event, CheckGameRunning at startup

* Fix image dragging

* fix

* Remove PWI

* fix updateLoop

* add webpack-dev-server to dev environment

* rm unnecessary chunks

* use <script setup>

* webpack-dev-server changes

* use <script setup>

* use <script setup>

* Fix UGC text size

* Split login event

* t

* use <script setup>

* fix

* Update .gitignore and enable checkJs in jsconfig

* fix i18n t

* use <script setup>

* use <script setup>

* clean

* global types

* fix

* use checkJs for debugging

* Add watchState for login watchers

* fix .vue template

* type fixes

* rm Vue.filter

* Cef v138.0.170, VC++ 2022

* Settings fixes

* Remove 'USER:CURRENT'

* clean up 2FA callbacks

* remove userApply

* rm i18n import

* notification handling to use notification store methods

* refactor favorite handling to use favorite store methods and clean up event emissions

* refactor moderation handling to use dedicated functions for player moderation events

* refactor friend handling to use dedicated functions for friend events

* Fix program startup, move lang init

* Fix friend state

* Fix status change error

* Fix user notes diff

* fix

* rm group event

* rm auth event

* rm avatar event

* clean

* clean

* getUser

* getFriends

* getFavoriteWorlds, getFavoriteAvatars

* AvatarGalleryUpload btn style & package.json update

* Fix friend requests

* Apply user

* Apply world

* Fix note diff

* Fix VR overlay

* Fixes

* Update build scripts

* Apply avatar

* Apply instance

* Apply group

* update hidden VRC+ badge

* Fix sameInstance "private"

* fix 502/504 API errors

* fix 502/504 API errors

* clean

* Fix friend in same instance on orange showing twice in friends list

* Add back in broken friend state repair methods

* add types

---------

Co-authored-by: Natsumi <cmcooper123@hotmail.com>
2025-07-14 15:00:08 +12:00

300 lines
9.8 KiB
JavaScript

import { defineStore } from 'pinia';
import { computed, reactive } from 'vue';
import * as workerTimers from 'worker-timers';
import { $app } from '../app';
import configRepository from '../service/config.js';
import { database } from '../service/database';
import {
deleteVRChatCache as _deleteVRChatCache,
isRealInstance
} from '../shared/utils';
import { useAvatarStore } from './avatar';
import { useGameLogStore } from './gameLog';
import { useInstanceStore } from './instance';
import { useLaunchStore } from './launch';
import { useLocationStore } from './location';
import { useNotificationStore } from './notification';
import { useAdvancedSettingsStore } from './settings/advanced';
import { useUpdateLoopStore } from './updateLoop';
import { useUserStore } from './user';
import { useVrStore } from './vr';
import { useWorldStore } from './world';
export const useGameStore = defineStore('Game', () => {
const advancedSettingsStore = useAdvancedSettingsStore();
const locationStore = useLocationStore();
const notificationStore = useNotificationStore();
const avatarStore = useAvatarStore();
const launchStore = useLaunchStore();
const worldStore = useWorldStore();
const instanceStore = useInstanceStore();
const gameLogStore = useGameLogStore();
const vrStore = useVrStore();
const userStore = useUserStore();
const updateLoopStore = useUpdateLoopStore();
const state = reactive({
lastCrashedTime: null,
VRChatUsedCacheSize: '',
VRChatTotalCacheSize: '',
VRChatCacheSizeLoading: false,
isGameRunning: false,
isGameNoVR: true,
isSteamVRRunning: false,
isHmdAfk: false
});
async function init() {
state.isGameNoVR = await configRepository.getBool('isGameNoVR');
}
init();
const VRChatUsedCacheSize = computed({
get: () => state.VRChatUsedCacheSize,
set: (value) => {
state.VRChatUsedCacheSize = value;
}
});
const VRChatTotalCacheSize = computed({
get: () => state.VRChatTotalCacheSize,
set: (value) => {
state.VRChatTotalCacheSize = value;
}
});
const VRChatCacheSizeLoading = computed({
get: () => state.VRChatCacheSizeLoading,
set: (value) => {
state.VRChatCacheSizeLoading = value;
}
});
const isGameRunning = computed({
get: () => state.isGameRunning,
set: (value) => {
state.isGameRunning = value;
}
});
const isGameNoVR = computed({
get: () => state.isGameNoVR,
set: (value) => {
state.isGameNoVR = value;
}
});
const isSteamVRRunning = computed({
get: () => state.isSteamVRRunning,
set: (value) => {
state.isSteamVRRunning = value;
}
});
const isHmdAfk = computed({
get: () => state.isHmdAfk,
set: (value) => {
state.isHmdAfk = value;
}
});
async function deleteVRChatCache(ref) {
await _deleteVRChatCache(ref);
getVRChatCacheSize();
worldStore.updateVRChatWorldCache();
avatarStore.updateVRChatAvatarCache();
}
function autoVRChatCacheManagement() {
if (advancedSettingsStore.autoSweepVRChatCache) {
sweepVRChatCache();
}
}
async function sweepVRChatCache() {
const output = await AssetBundleManager.SweepCache();
console.log('SweepCache', output);
if (advancedSettingsStore.isVRChatConfigDialogVisible) {
getVRChatCacheSize();
}
}
function checkIfGameCrashed() {
if (!advancedSettingsStore.relaunchVRChatAfterCrash) {
return;
}
const { location } = locationStore.lastLocation;
AppApi.VrcClosedGracefully().then((result) => {
if (result || !isRealInstance(location)) {
return;
}
// check if relaunched less than 2mins ago (prvent crash loop)
if (
state.lastCrashedTime &&
new Date() - state.lastCrashedTime < 120_000
) {
console.log('VRChat was recently crashed, not relaunching');
return;
}
state.lastCrashedTime = new Date();
// wait a bit for SteamVR to potentially close before deciding to relaunch
let restartDelay = 8000;
if (state.isGameNoVR) {
// wait for game to close before relaunching
restartDelay = 2000;
}
workerTimers.setTimeout(
() => restartCrashedGame(location),
restartDelay
);
});
}
function restartCrashedGame(location) {
if (!state.isGameNoVR && !state.isSteamVRRunning) {
console.log("SteamVR isn't running, not relaunching VRChat");
return;
}
AppApi.FocusWindow();
const message = 'VRChat crashed, attempting to rejoin last instance';
$app.$message({
message,
type: 'info'
});
const entry = {
created_at: new Date().toJSON(),
type: 'Event',
data: message
};
database.addGamelogEventToDatabase(entry);
notificationStore.queueGameLogNoty(entry);
gameLogStore.addGameLog(entry);
launchStore.launchGame(location, '', state.isGameNoVR);
}
async function getVRChatCacheSize() {
state.VRChatCacheSizeLoading = true;
const totalCacheSize = 30;
state.VRChatTotalCacheSize = totalCacheSize;
const usedCacheSize = await AssetBundleManager.GetCacheSize();
state.VRChatUsedCacheSize = (usedCacheSize / 1073741824).toFixed(2);
state.VRChatCacheSizeLoading = false;
}
// use in C#
async function updateIsGameRunning(
isGameRunning,
isSteamVRRunning,
isHmdAfk
) {
const avatarStore = useAvatarStore();
if (advancedSettingsStore.gameLogDisabled) {
return;
}
if (isGameRunning !== state.isGameRunning) {
state.isGameRunning = isGameRunning;
if (isGameRunning) {
userStore.currentUser.$online_for = Date.now();
userStore.currentUser.$offline_for = '';
userStore.currentUser.$previousAvatarSwapTime = Date.now();
} else {
await configRepository.setBool('isGameNoVR', state.isGameNoVR);
userStore.currentUser.$online_for = '';
userStore.currentUser.$offline_for = Date.now();
instanceStore.removeAllQueuedInstances();
autoVRChatCacheManagement();
checkIfGameCrashed();
updateLoopStore.ipcTimeout = 0;
avatarStore.addAvatarWearTime(
userStore.currentUser.currentAvatar
);
userStore.currentUser.$previousAvatarSwapTime = '';
}
locationStore.lastLocationReset();
gameLogStore.clearNowPlaying();
vrStore.updateVRLastLocation();
workerTimers.setTimeout(() => checkVRChatDebugLogging(), 60000);
updateLoopStore.nextDiscordUpdate = 0;
console.log(new Date(), 'isGameRunning', isGameRunning);
}
if (isSteamVRRunning !== state.isSteamVRRunning) {
state.isSteamVRRunning = isSteamVRRunning;
console.log('isSteamVRRunning:', isSteamVRRunning);
}
if (isHmdAfk !== state.isHmdAfk) {
state.isHmdAfk = isHmdAfk;
console.log('isHmdAfk:', isHmdAfk);
}
vrStore.updateOpenVR();
}
async function checkVRChatDebugLogging() {
if (advancedSettingsStore.gameLogDisabled) {
return;
}
try {
const loggingEnabled =
await getVRChatRegistryKey('LOGGING_ENABLED');
if (
loggingEnabled === null ||
typeof loggingEnabled === 'undefined'
) {
// key not found
return;
}
if (parseInt(loggingEnabled, 10) === 1) {
// already enabled
return;
}
const result = await AppApi.SetVRChatRegistryKey(
'LOGGING_ENABLED',
'1',
4
);
if (!result) {
// failed to set key
$app.$alert(
'VRCX has noticed VRChat debug logging is disabled. VRCX requires debug logging in order to function correctly. Please enable debug logging in VRChat quick menu settings > debug > enable debug logging, then rejoin the instance or restart VRChat.',
'Enable debug logging'
);
console.error('Failed to enable debug logging', result);
return;
}
$app.$alert(
'VRCX has noticed VRChat debug logging is disabled and automatically re-enabled it. VRCX requires debug logging in order to function correctly.',
'Enabled debug logging'
);
console.log('Enabled debug logging');
} catch (e) {
console.error(e);
}
}
async function getVRChatRegistryKey(key) {
if (LINUX) {
return AppApi.GetVRChatRegistryKeyString(key);
}
return AppApi.GetVRChatRegistryKey(key);
}
return {
state,
VRChatUsedCacheSize,
VRChatTotalCacheSize,
VRChatCacheSizeLoading,
isGameRunning,
isGameNoVR,
isSteamVRRunning,
isHmdAfk,
deleteVRChatCache,
sweepVRChatCache,
getVRChatCacheSize,
updateIsGameRunning,
getVRChatRegistryKey,
checkVRChatDebugLogging
};
});