mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-17 13:53:52 +02:00
1868 lines
70 KiB
JavaScript
1868 lines
70 KiB
JavaScript
import { computed, reactive, ref } from 'vue';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import { defineStore } from 'pinia';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
import {
|
|
checkVRChatCache,
|
|
displayLocation,
|
|
getGroupName,
|
|
getWorldName,
|
|
parseLocation,
|
|
removeFromArray,
|
|
replaceBioSymbols,
|
|
timeToText
|
|
} from '../shared/utils';
|
|
import { instanceRequest, userRequest } from '../api';
|
|
import { photonEmojis, photonEventType } from '../shared/constants/photon';
|
|
import { AppDebug } from '../service/appConfig';
|
|
import { database } from '../service/database';
|
|
import { useAvatarStore } from './avatar';
|
|
import { useFavoriteStore } from './favorite';
|
|
import { useFriendStore } from './friend';
|
|
import { useGameLogStore } from './gameLog';
|
|
import { useInstanceStore } from './instance';
|
|
import { useLocationStore } from './location';
|
|
import { useNotificationStore } from './notification';
|
|
import { useSharedFeedStore } from './sharedFeed';
|
|
import { useUserStore } from './user';
|
|
import { useVrStore } from './vr';
|
|
|
|
import configRepository from '../service/config';
|
|
|
|
import * as workerTimers from 'worker-timers';
|
|
|
|
export const usePhotonStore = defineStore('Photon', () => {
|
|
const vrStore = useVrStore();
|
|
const userStore = useUserStore();
|
|
const friendStore = useFriendStore();
|
|
const instanceStore = useInstanceStore();
|
|
const gameLogStore = useGameLogStore();
|
|
const notificationStore = useNotificationStore();
|
|
const locationStore = useLocationStore();
|
|
const sharedFeedStore = useSharedFeedStore();
|
|
const avatarStore = useAvatarStore();
|
|
const favoriteStore = useFavoriteStore();
|
|
const { t } = useI18n();
|
|
|
|
const state = reactive({
|
|
photonEventTableTypeFilterList: [
|
|
'Event',
|
|
'OnPlayerJoined',
|
|
'OnPlayerLeft',
|
|
'ChangeAvatar',
|
|
'ChangeStatus',
|
|
'ChangeGroup',
|
|
'PortalSpawn',
|
|
'DeletedPortal',
|
|
'ChatBoxMessage',
|
|
'Moderation',
|
|
'Camera',
|
|
'SpawnEmoji',
|
|
'MasterMigrate'
|
|
],
|
|
photonEventCount: 0,
|
|
photonLobbyTimeoutThreshold: 6000,
|
|
photonOverlayMessageTimeout: 6000,
|
|
//
|
|
photonLobbyWatcherLoop: false
|
|
});
|
|
|
|
const photonLobby = ref(new Map());
|
|
const photonLobbyMaster = ref(0);
|
|
const photonLobbyCurrentUser = ref(0);
|
|
const photonLobbyUserData = ref(new Map());
|
|
const photonLobbyCurrent = ref(new Map());
|
|
const photonLobbyAvatars = ref(new Map());
|
|
const photonLobbyLastModeration = ref(new Map());
|
|
const photonLobbyTimeout = ref([]);
|
|
const photonLobbyJointime = ref(new Map());
|
|
const photonLobbyActivePortals = ref(new Map());
|
|
const photonEvent7List = ref(new Map());
|
|
const photonLastEvent7List = ref(0);
|
|
const photonLastChatBoxMsg = ref(new Map());
|
|
const moderationEventQueue = ref(new Map());
|
|
const photonLoggingEnabled = ref(false);
|
|
const photonEventOverlay = ref(false);
|
|
const photonEventOverlayFilter = ref('Everyone');
|
|
const photonEventTableTypeOverlayFilter = ref([]);
|
|
const timeoutHudOverlay = ref(false);
|
|
const timeoutHudOverlayFilter = ref('Everyone');
|
|
const photonEventIcon = ref(false);
|
|
const photonEventTable = ref({
|
|
data: [],
|
|
filters: [
|
|
{
|
|
prop: ['displayName', 'text'],
|
|
value: ''
|
|
},
|
|
{
|
|
prop: 'type',
|
|
value: []
|
|
}
|
|
],
|
|
tableProps: {
|
|
stripe: true,
|
|
size: 'small'
|
|
},
|
|
pageSize: 10,
|
|
paginationProps: {
|
|
layout: 'sizes,prev,pager,next,total'
|
|
}
|
|
});
|
|
const photonEventTablePrevious = ref({
|
|
data: [],
|
|
filters: [
|
|
{
|
|
prop: ['displayName', 'text'],
|
|
value: ''
|
|
},
|
|
{
|
|
prop: 'type',
|
|
value: []
|
|
}
|
|
],
|
|
tableProps: {
|
|
stripe: true,
|
|
size: 'small'
|
|
},
|
|
pageSize: 10,
|
|
paginationProps: {
|
|
layout: 'sizes,prev,pager,next,total'
|
|
}
|
|
});
|
|
const chatboxUserBlacklist = ref(new Map());
|
|
const chatboxBlacklist = ref([
|
|
'NP: ',
|
|
'Now Playing',
|
|
'Now playing',
|
|
"▶️ '",
|
|
'( ▶️ ',
|
|
"' - '",
|
|
"' by '",
|
|
'[Spotify] '
|
|
]);
|
|
const photonEventTableFilter = ref('');
|
|
const moderationAgainstTable = ref([]);
|
|
const photonEventTableTypeFilter = ref([]);
|
|
|
|
async function initPhotonStates() {
|
|
const [
|
|
photonEventOverlayConfig,
|
|
photonEventOverlayFilterConfig,
|
|
photonEventTableTypeOverlayFilterConfig,
|
|
timeoutHudOverlayConfig,
|
|
timeoutHudOverlayFilterConfig,
|
|
photonLobbyTimeoutThresholdConfig,
|
|
photonOverlayMessageTimeoutConfig,
|
|
photonEventTableTypeFilterConfig,
|
|
chatboxUserBlacklistConfig,
|
|
chatboxKeywordBlacklistConfig
|
|
] = await Promise.all([
|
|
configRepository.getBool('VRCX_PhotonEventOverlay', false),
|
|
configRepository.getString(
|
|
'VRCX_PhotonEventOverlayFilter',
|
|
'Everyone'
|
|
),
|
|
configRepository.getString(
|
|
'VRCX_photonEventTypeOverlayFilter',
|
|
'[]'
|
|
),
|
|
configRepository.getBool('VRCX_TimeoutHudOverlay', false),
|
|
configRepository.getString(
|
|
'VRCX_TimeoutHudOverlayFilter',
|
|
'Everyone'
|
|
),
|
|
configRepository.getInt('VRCX_photonLobbyTimeoutThreshold', 6000),
|
|
configRepository.getString(
|
|
'VRCX_photonOverlayMessageTimeout',
|
|
(6000).toString()
|
|
),
|
|
configRepository.getString('VRCX_photonEventTypeFilter', '[]'),
|
|
configRepository.getString('VRCX_chatboxUserBlacklist'),
|
|
configRepository.getString('VRCX_chatboxBlacklist')
|
|
]);
|
|
|
|
photonEventOverlay.value = photonEventOverlayConfig;
|
|
photonEventOverlayFilter.value = photonEventOverlayFilterConfig;
|
|
photonEventTableTypeOverlayFilter.value = JSON.parse(
|
|
photonEventTableTypeOverlayFilterConfig
|
|
);
|
|
timeoutHudOverlay.value = timeoutHudOverlayConfig;
|
|
timeoutHudOverlayFilter.value = timeoutHudOverlayFilterConfig;
|
|
photonLobbyTimeoutThreshold.value = photonLobbyTimeoutThresholdConfig;
|
|
photonOverlayMessageTimeout.value = Number(
|
|
photonOverlayMessageTimeoutConfig
|
|
);
|
|
photonEventTableTypeFilter.value = JSON.parse(
|
|
photonEventTableTypeFilterConfig
|
|
);
|
|
|
|
photonEventTable.value.filters[1].value =
|
|
photonEventTableTypeFilter.value;
|
|
photonEventTablePrevious.value.filters[1].value =
|
|
photonEventTableTypeFilter.value;
|
|
|
|
chatboxUserBlacklist.value = new Map(
|
|
Object.entries(JSON.parse(chatboxUserBlacklistConfig || '{}'))
|
|
);
|
|
|
|
try {
|
|
if (chatboxKeywordBlacklistConfig) {
|
|
const arr = JSON.parse(chatboxKeywordBlacklistConfig);
|
|
if (Array.isArray(arr)) {
|
|
chatboxBlacklist.value = arr;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error(
|
|
'Failed to parse chatbox keyword blacklist config',
|
|
err
|
|
);
|
|
}
|
|
}
|
|
|
|
initPhotonStates();
|
|
|
|
const photonLobbyTimeoutThreshold = computed({
|
|
get: () => state.photonLobbyTimeoutThreshold,
|
|
set: (value) => {
|
|
state.photonLobbyTimeoutThreshold = value;
|
|
configRepository.setString(
|
|
'VRCX_photonLobbyTimeoutThreshold',
|
|
value.toString()
|
|
);
|
|
}
|
|
});
|
|
const photonOverlayMessageTimeout = computed({
|
|
get: () => state.photonOverlayMessageTimeout,
|
|
set: (value) => {
|
|
state.photonOverlayMessageTimeout = value;
|
|
configRepository.setString(
|
|
'VRCX_photonOverlayMessageTimeout',
|
|
value.toString()
|
|
);
|
|
}
|
|
});
|
|
|
|
function setPhotonLoggingEnabled() {
|
|
photonLoggingEnabled.value = !photonLoggingEnabled.value;
|
|
configRepository.setBool('VRCX_photonLoggingEnabled', true);
|
|
}
|
|
function setPhotonEventOverlay() {
|
|
photonEventOverlay.value = !photonEventOverlay.value;
|
|
configRepository.setBool(
|
|
'VRCX_PhotonEventOverlay',
|
|
photonEventOverlay.value
|
|
);
|
|
}
|
|
|
|
function setPhotonEventOverlayFilter(value) {
|
|
photonEventOverlayFilter.value = value;
|
|
configRepository.setString(
|
|
'VRCX_PhotonEventOverlayFilter',
|
|
photonEventOverlayFilter.value
|
|
);
|
|
}
|
|
function setPhotonEventTableTypeOverlayFilter(value) {
|
|
photonEventTableTypeOverlayFilter.value = value;
|
|
configRepository.setString(
|
|
'VRCX_photonEventTypeOverlayFilter',
|
|
JSON.stringify(photonEventTableTypeOverlayFilter.value)
|
|
);
|
|
}
|
|
function setTimeoutHudOverlay(value) {
|
|
timeoutHudOverlay.value = !timeoutHudOverlay.value;
|
|
configRepository.setBool('VRCX_TimeoutHudOverlay', value);
|
|
if (!timeoutHudOverlay.value) {
|
|
AppApi.ExecuteVrOverlayFunction('updateHudTimeout', '[]');
|
|
}
|
|
}
|
|
function setTimeoutHudOverlayFilter(value) {
|
|
timeoutHudOverlayFilter.value = value;
|
|
configRepository.setString(
|
|
'VRCX_TimeoutHudOverlayFilter',
|
|
timeoutHudOverlayFilter.value
|
|
);
|
|
}
|
|
|
|
function getDisplayName(userId) {
|
|
if (userId) {
|
|
const ref = userStore.cachedUsers.get(userId);
|
|
if (ref.displayName) {
|
|
return ref.displayName;
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
function photonEventPulse() {
|
|
state.photonEventCount++;
|
|
photonEventIcon.value = true;
|
|
workerTimers.setTimeout(() => (photonEventIcon.value = false), 150);
|
|
}
|
|
|
|
async function saveEventOverlay(configKey = '') {
|
|
if (configKey === 'VRCX_PhotonEventOverlay') {
|
|
setPhotonEventOverlay();
|
|
} else if (configKey === 'VRCX_TimeoutHudOverlay') {
|
|
setTimeoutHudOverlay();
|
|
}
|
|
vrStore.updateOpenVR();
|
|
vrStore.updateVRConfigVars();
|
|
}
|
|
|
|
function parseOperationResponse(data, dateTime) {
|
|
switch (data.OperationCode) {
|
|
case 226:
|
|
if (
|
|
typeof data.Parameters[248] !== 'undefined' &&
|
|
typeof data.Parameters[248][248] !== 'undefined'
|
|
) {
|
|
setPhotonLobbyMaster(data.Parameters[248][248]);
|
|
}
|
|
if (typeof data.Parameters[254] !== 'undefined') {
|
|
photonLobbyCurrentUser.value = data.Parameters[254];
|
|
}
|
|
if (typeof data.Parameters[249] !== 'undefined') {
|
|
for (const i in data.Parameters[249]) {
|
|
const idNum = safeParseInt(i);
|
|
if (idNum === null) continue;
|
|
const user = data.Parameters[249][i];
|
|
if (!user || !user.user) continue;
|
|
parsePhotonUser(idNum, user.user, dateTime);
|
|
if (user.avatarDict) {
|
|
parsePhotonAvatarChange(
|
|
idNum,
|
|
user.user,
|
|
user.avatarDict,
|
|
dateTime
|
|
);
|
|
parsePhotonAvatar(user.avatarDict);
|
|
}
|
|
if (user.favatarDict) {
|
|
parsePhotonAvatar(user.favatarDict);
|
|
}
|
|
if (typeof user.groupOnNameplate !== 'undefined') {
|
|
parsePhotonGroupChange(
|
|
idNum,
|
|
user.user,
|
|
user.groupOnNameplate,
|
|
dateTime
|
|
);
|
|
}
|
|
let hasInstantiated = false;
|
|
const lobbyJointime =
|
|
photonLobbyJointime.value.get(idNum);
|
|
if (typeof lobbyJointime !== 'undefined') {
|
|
hasInstantiated = lobbyJointime.hasInstantiated;
|
|
}
|
|
photonLobbyJointime.value.set(idNum, {
|
|
joinTime: Date.parse(dateTime),
|
|
hasInstantiated,
|
|
inVRMode: user.inVRMode,
|
|
avatarEyeHeight: user.avatarEyeHeight,
|
|
canModerateInstance: user.canModerateInstance,
|
|
groupOnNameplate: user.groupOnNameplate,
|
|
showGroupBadgeToOthers: user.showGroupBadgeToOthers,
|
|
showSocialRank: user.showSocialRank,
|
|
useImpostorAsFallback: user.useImpostorAsFallback,
|
|
platform: user.platform
|
|
});
|
|
}
|
|
}
|
|
if (typeof data.Parameters[252] !== 'undefined') {
|
|
parsePhotonLobbyIds(data.Parameters[252]);
|
|
}
|
|
photonEvent7List.value = new Map();
|
|
break;
|
|
}
|
|
}
|
|
|
|
function checkChatboxBlacklist(msg) {
|
|
if (typeof msg !== 'string') return false;
|
|
const list = chatboxBlacklist.value || [];
|
|
for (let i = 0; i < list.length; ++i) {
|
|
const kw = list[i];
|
|
if (!kw) continue;
|
|
if (msg.includes(kw)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async function saveChatboxUserBlacklist() {
|
|
await configRepository.setString(
|
|
'VRCX_chatboxUserBlacklist',
|
|
JSON.stringify(Object.fromEntries(chatboxUserBlacklist.value))
|
|
);
|
|
}
|
|
|
|
async function saveChatboxBlacklist() {
|
|
await configRepository.setString(
|
|
'VRCX_chatboxBlacklist',
|
|
JSON.stringify(chatboxBlacklist.value)
|
|
);
|
|
}
|
|
|
|
async function photonEventTableFilterChange() {
|
|
photonEventTable.value.filters[0].value = photonEventTableFilter.value;
|
|
photonEventTable.value.filters[1].value =
|
|
photonEventTableTypeFilter.value;
|
|
|
|
photonEventTablePrevious.value.filters[0].value =
|
|
photonEventTableFilter.value;
|
|
photonEventTablePrevious.value.filters[1].value =
|
|
photonEventTableTypeFilter.value;
|
|
|
|
await configRepository.setString(
|
|
'VRCX_photonEventTypeFilter',
|
|
JSON.stringify(photonEventTableTypeFilter.value)
|
|
);
|
|
// await configRepository.setString(
|
|
// 'VRCX_photonEventTypeOverlayFilter',
|
|
// JSON.stringify(this.photonEventTableTypeOverlayFilter)
|
|
// );
|
|
}
|
|
|
|
function showUserFromPhotonId(photonId) {
|
|
if (photonId) {
|
|
const ref = photonLobby.value.get(photonId);
|
|
if (typeof ref !== 'undefined') {
|
|
if (typeof ref.id !== 'undefined') {
|
|
userStore.showUserDialog(ref.id);
|
|
} else if (typeof ref.displayName !== 'undefined') {
|
|
userStore.lookupUser(ref);
|
|
}
|
|
} else {
|
|
ElMessage({
|
|
message: 'No user info available',
|
|
type: 'error'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function promptPhotonOverlayMessageTimeout() {
|
|
ElMessageBox.prompt(
|
|
t('prompt.overlay_message_timeout.description'),
|
|
t('prompt.overlay_message_timeout.header'),
|
|
{
|
|
distinguishCancelAndClose: true,
|
|
confirmButtonText: t('prompt.overlay_message_timeout.ok'),
|
|
cancelButtonText: t('prompt.overlay_message_timeout.cancel'),
|
|
inputValue: (
|
|
state.photonOverlayMessageTimeout / 1000
|
|
).toString(),
|
|
inputPattern: /\d+$/,
|
|
inputErrorMessage: t(
|
|
'prompt.overlay_message_timeout.input_error'
|
|
)
|
|
}
|
|
)
|
|
.then(({ value, action }) => {
|
|
if (action === 'confirm' && value && !isNaN(Number(value))) {
|
|
state.photonOverlayMessageTimeout = Math.trunc(
|
|
Number(value) * 1000
|
|
);
|
|
vrStore.updateVRConfigVars();
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
}
|
|
|
|
function promptPhotonLobbyTimeoutThreshold() {
|
|
ElMessageBox.prompt(
|
|
t('prompt.photon_lobby_timeout.description'),
|
|
t('prompt.photon_lobby_timeout.header'),
|
|
{
|
|
distinguishCancelAndClose: true,
|
|
confirmButtonText: t('prompt.photon_lobby_timeout.ok'),
|
|
cancelButtonText: t('prompt.photon_lobby_timeout.cancel'),
|
|
inputValue: (
|
|
state.photonLobbyTimeoutThreshold / 1000
|
|
).toString(),
|
|
inputPattern: /\d+$/,
|
|
inputErrorMessage: t('prompt.photon_lobby_timeout.input_error')
|
|
}
|
|
)
|
|
.then(({ value, action }) => {
|
|
if (action === 'confirm' && value && !isNaN(Number(value))) {
|
|
state.photonLobbyTimeoutThreshold = Math.trunc(
|
|
Number(value) * 1000
|
|
);
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
}
|
|
|
|
function startLobbyWatcherLoop() {
|
|
if (!state.photonLobbyWatcherLoop) {
|
|
state.photonLobbyWatcherLoop = true;
|
|
photonLobbyWatcher();
|
|
}
|
|
}
|
|
|
|
function photonLobbyWatcherLoopStop() {
|
|
state.photonLobbyWatcherLoop = false;
|
|
photonLobbyTimeout.value = [];
|
|
AppApi.ExecuteVrOverlayFunction('updateHudTimeout', '[]');
|
|
}
|
|
|
|
function photonLobbyWatcher() {
|
|
if (!state.photonLobbyWatcherLoop) {
|
|
return;
|
|
}
|
|
if (photonLobbyCurrent.value.size === 0) {
|
|
photonLobbyWatcherLoopStop();
|
|
return;
|
|
}
|
|
const dtNow = Date.now();
|
|
const bias2 = photonLastEvent7List.value + 1.5 * 1000;
|
|
if (dtNow > bias2 || locationStore.lastLocation.playerList.size <= 1) {
|
|
if (photonLobbyTimeout.value.length > 0) {
|
|
AppApi.ExecuteVrOverlayFunction('updateHudTimeout', '[]');
|
|
}
|
|
photonLobbyTimeout.value = [];
|
|
workerTimers.setTimeout(() => photonLobbyWatcher(), 500);
|
|
return;
|
|
}
|
|
const hudTimeout = [];
|
|
photonEvent7List.value.forEach((dt, id) => {
|
|
const timeSinceLastEvent = dtNow - Date.parse(dt);
|
|
if (
|
|
timeSinceLastEvent > state.photonLobbyTimeoutThreshold &&
|
|
id !== photonLobbyCurrentUser.value
|
|
) {
|
|
if (photonLobbyJointime.value.has(id)) {
|
|
var { joinTime } = photonLobbyJointime.value.get(id);
|
|
}
|
|
if (!joinTime) {
|
|
console.log(`${id} missing join time`);
|
|
}
|
|
if (joinTime && joinTime + 70000 < dtNow) {
|
|
// wait 70secs for user to load in
|
|
hudTimeout.unshift({
|
|
userId: getUserIdFromPhotonId(id),
|
|
displayName: getDisplayNameFromPhotonId(id),
|
|
time: Math.round(timeSinceLastEvent / 1000),
|
|
rawTime: timeSinceLastEvent
|
|
});
|
|
}
|
|
}
|
|
});
|
|
if (photonLobbyTimeout.value.length > 0 || hudTimeout.length > 0) {
|
|
hudTimeout.sort(function (a, b) {
|
|
if (a.rawTime > b.rawTime) {
|
|
return 1;
|
|
}
|
|
if (a.rawTime < b.rawTime) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
});
|
|
if (timeoutHudOverlay.value) {
|
|
if (
|
|
timeoutHudOverlayFilter.value === 'VIP' ||
|
|
timeoutHudOverlayFilter.value === 'Friends'
|
|
) {
|
|
var filteredHudTimeout = [];
|
|
hudTimeout.forEach((item) => {
|
|
if (
|
|
timeoutHudOverlayFilter.value === 'VIP' &&
|
|
favoriteStore.getCachedFavoritesByObjectId(
|
|
item.userId
|
|
)
|
|
) {
|
|
filteredHudTimeout.push(item);
|
|
} else if (
|
|
timeoutHudOverlayFilter.value === 'Friends' &&
|
|
friendStore.friends.has(item.userId)
|
|
) {
|
|
filteredHudTimeout.push(item);
|
|
}
|
|
});
|
|
} else {
|
|
var filteredHudTimeout = hudTimeout;
|
|
}
|
|
AppApi.ExecuteVrOverlayFunction(
|
|
'updateHudTimeout',
|
|
JSON.stringify(filteredHudTimeout)
|
|
);
|
|
}
|
|
photonLobbyTimeout.value = hudTimeout;
|
|
instanceStore.getCurrentInstanceUserList();
|
|
}
|
|
workerTimers.setTimeout(() => photonLobbyWatcher(), 500);
|
|
}
|
|
|
|
function addEntryPhotonEvent(input) {
|
|
let isMaster = false;
|
|
if (input.photonId === photonLobbyMaster.value) {
|
|
isMaster = true;
|
|
}
|
|
const joinTimeRef = photonLobbyJointime.value.get(input.photonId);
|
|
const isModerator = joinTimeRef?.canModerateInstance;
|
|
const photonUserRef = photonLobby.value.get(input.photonId);
|
|
let displayName = '';
|
|
let userId = '';
|
|
let isFriend = false;
|
|
if (typeof photonUserRef !== 'undefined') {
|
|
displayName = photonUserRef.displayName;
|
|
userId = photonUserRef.id;
|
|
isFriend = photonUserRef.isFriend;
|
|
}
|
|
const isFavorite = friendStore.localFavoriteFriends.has(userId);
|
|
let colour = '';
|
|
const tagRef = userStore.customUserTags.get(userId);
|
|
if (typeof tagRef !== 'undefined') {
|
|
colour = tagRef.colour;
|
|
}
|
|
const feed = {
|
|
displayName,
|
|
userId,
|
|
isFavorite,
|
|
isFriend,
|
|
isMaster,
|
|
isModerator,
|
|
colour,
|
|
...input
|
|
};
|
|
photonEventTable.value.data.unshift(feed);
|
|
if (
|
|
photonEventTableTypeOverlayFilter.value.length > 0 &&
|
|
!photonEventTableTypeOverlayFilter.value.includes(feed.type)
|
|
) {
|
|
return;
|
|
}
|
|
if (photonEventOverlay.value) {
|
|
if (
|
|
photonEventOverlayFilter.value === 'VIP' ||
|
|
photonEventOverlayFilter.value === 'Friends'
|
|
) {
|
|
if (
|
|
feed.userId &&
|
|
((photonEventOverlayFilter.value === 'VIP' && isFavorite) ||
|
|
(photonEventOverlayFilter.value === 'Friends' &&
|
|
isFriend))
|
|
) {
|
|
AppApi.ExecuteVrOverlayFunction(
|
|
'addEntryHudFeed',
|
|
JSON.stringify(feed)
|
|
);
|
|
}
|
|
} else {
|
|
AppApi.ExecuteVrOverlayFunction(
|
|
'addEntryHudFeed',
|
|
JSON.stringify(feed)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getDisplayNameFromPhotonId(photonId) {
|
|
let displayName = '';
|
|
if (photonId) {
|
|
const ref = photonLobby.value.get(photonId);
|
|
displayName = `ID:${photonId}`;
|
|
if (
|
|
typeof ref !== 'undefined' &&
|
|
typeof ref.displayName !== 'undefined'
|
|
) {
|
|
displayName = ref.displayName;
|
|
}
|
|
}
|
|
return displayName;
|
|
}
|
|
|
|
function getUserIdFromPhotonId(photonId) {
|
|
let userId = '';
|
|
if (photonId) {
|
|
const ref = photonLobby.value.get(photonId);
|
|
if (typeof ref !== 'undefined' && typeof ref.id !== 'undefined') {
|
|
userId = ref.id;
|
|
}
|
|
}
|
|
return userId;
|
|
}
|
|
|
|
function getPhotonIdFromDisplayName(displayName) {
|
|
let photonId = '';
|
|
if (displayName) {
|
|
photonLobby.value.forEach((ref, id) => {
|
|
if (
|
|
typeof ref !== 'undefined' &&
|
|
ref.displayName === displayName
|
|
) {
|
|
photonId = id;
|
|
}
|
|
});
|
|
}
|
|
return photonId;
|
|
}
|
|
|
|
function getPhotonIdFromUserId(userId) {
|
|
let photonId = '';
|
|
if (userId) {
|
|
photonLobby.value.forEach((ref, id) => {
|
|
if (typeof ref !== 'undefined' && ref.id === userId) {
|
|
photonId = id;
|
|
}
|
|
});
|
|
}
|
|
return photonId;
|
|
}
|
|
|
|
// function sortPhotonId(a, b, field) {
|
|
// const id1 = getPhotonIdFromDisplayName(a[field]);
|
|
// const id2 = getPhotonIdFromDisplayName(b[field]);
|
|
// if (id1 < id2) {
|
|
// return 1;
|
|
// }
|
|
// if (id1 > id2) {
|
|
// return -1;
|
|
// }
|
|
// return 0;
|
|
// }
|
|
|
|
function parsePhotonEvent(data, gameLogDate) {
|
|
switch (data.Code) {
|
|
case 253:
|
|
// SetUserProperties
|
|
if (data.Parameters[253] === -1) {
|
|
for (let i in data.Parameters[251]) {
|
|
const idNum = safeParseInt(i);
|
|
if (idNum === null) continue;
|
|
const user = data.Parameters[251][i];
|
|
if (!user || !user.user) continue;
|
|
parsePhotonUser(idNum, user.user, gameLogDate);
|
|
if (user.avatarDict) {
|
|
parsePhotonAvatarChange(
|
|
idNum,
|
|
user.user,
|
|
user.avatarDict,
|
|
gameLogDate
|
|
);
|
|
parsePhotonAvatar(user.avatarDict);
|
|
}
|
|
if (user.favatarDict) {
|
|
parsePhotonAvatar(user.favatarDict);
|
|
}
|
|
if (typeof user.groupOnNameplate !== 'undefined') {
|
|
parsePhotonGroupChange(
|
|
idNum,
|
|
user.user,
|
|
user.groupOnNameplate,
|
|
gameLogDate
|
|
);
|
|
}
|
|
var hasInstantiated = false;
|
|
var lobbyJointime =
|
|
photonLobbyJointime.value.get(idNum);
|
|
if (typeof lobbyJointime !== 'undefined') {
|
|
hasInstantiated = lobbyJointime.hasInstantiated;
|
|
}
|
|
photonLobbyJointime.value.set(idNum, {
|
|
joinTime: Date.parse(gameLogDate),
|
|
hasInstantiated,
|
|
inVRMode: user.inVRMode,
|
|
avatarEyeHeight: user.avatarEyeHeight,
|
|
canModerateInstance: user.canModerateInstance,
|
|
groupOnNameplate: user.groupOnNameplate,
|
|
showGroupBadgeToOthers: user.showGroupBadgeToOthers,
|
|
showSocialRank: user.showSocialRank,
|
|
useImpostorAsFallback: user.useImpostorAsFallback,
|
|
platform: user.platform
|
|
});
|
|
photonUserJoin(idNum, user, gameLogDate);
|
|
}
|
|
} else {
|
|
console.log('oldSetUserProps', data);
|
|
const idNum = safeParseInt(data.Parameters[253]);
|
|
if (idNum === null) break;
|
|
const user = data.Parameters[251];
|
|
if (!user || !user.user) break;
|
|
parsePhotonUser(idNum, user.user, gameLogDate);
|
|
if (user.avatarDict) {
|
|
parsePhotonAvatarChange(
|
|
idNum,
|
|
user.user,
|
|
user.avatarDict,
|
|
gameLogDate
|
|
);
|
|
parsePhotonAvatar(user.avatarDict);
|
|
}
|
|
if (user.favatarDict) {
|
|
parsePhotonAvatar(user.favatarDict);
|
|
}
|
|
if (typeof user.groupOnNameplate !== 'undefined') {
|
|
parsePhotonGroupChange(
|
|
idNum,
|
|
user.user,
|
|
user.groupOnNameplate,
|
|
gameLogDate
|
|
);
|
|
}
|
|
var hasInstantiated = false;
|
|
var lobbyJointime = photonLobbyJointime.value.get(idNum);
|
|
if (typeof lobbyJointime !== 'undefined') {
|
|
hasInstantiated = lobbyJointime.hasInstantiated;
|
|
}
|
|
photonLobbyJointime.value.set(idNum, {
|
|
joinTime: Date.parse(gameLogDate),
|
|
hasInstantiated,
|
|
inVRMode: user.inVRMode,
|
|
avatarEyeHeight: user.avatarEyeHeight,
|
|
canModerateInstance: user.canModerateInstance,
|
|
groupOnNameplate: user.groupOnNameplate,
|
|
showGroupBadgeToOthers: user.showGroupBadgeToOthers,
|
|
showSocialRank: user.showSocialRank,
|
|
useImpostorAsFallback: user.useImpostorAsFallback,
|
|
platform: user.platform
|
|
});
|
|
photonUserJoin(idNum, user, gameLogDate);
|
|
}
|
|
break;
|
|
case 42:
|
|
// SetUserProperties
|
|
var id42 = safeParseInt(data.Parameters[254]);
|
|
var user42 = data.Parameters[245];
|
|
if (id42 === null || !user42 || !user42.user) break;
|
|
parsePhotonUser(id42, user42.user, gameLogDate);
|
|
if (user42.avatarDict) {
|
|
parsePhotonAvatarChange(
|
|
id42,
|
|
user42.user,
|
|
user42.avatarDict,
|
|
gameLogDate
|
|
);
|
|
parsePhotonAvatar(user42.avatarDict);
|
|
}
|
|
if (user42.favatarDict) {
|
|
parsePhotonAvatar(user42.favatarDict);
|
|
}
|
|
if (typeof user42.groupOnNameplate !== 'undefined') {
|
|
parsePhotonGroupChange(
|
|
id42,
|
|
user42.user,
|
|
user42.groupOnNameplate,
|
|
gameLogDate
|
|
);
|
|
}
|
|
var lobbyJointime = photonLobbyJointime.value.get(id42);
|
|
photonLobbyJointime.value.set(id42, {
|
|
hasInstantiated: true,
|
|
...lobbyJointime,
|
|
inVRMode: user42.inVRMode,
|
|
avatarEyeHeight: user42.avatarEyeHeight,
|
|
canModerateInstance: user42.canModerateInstance,
|
|
groupOnNameplate: user42.groupOnNameplate,
|
|
showGroupBadgeToOthers: user42.showGroupBadgeToOthers,
|
|
showSocialRank: user42.showSocialRank,
|
|
useImpostorAsFallback: user42.useImpostorAsFallback,
|
|
platform: user42.platform
|
|
});
|
|
break;
|
|
case 255:
|
|
// Join
|
|
const id255 = safeParseInt(data.Parameters[254]);
|
|
if (id255 === null) break;
|
|
if (typeof data.Parameters[249] !== 'undefined') {
|
|
const u255 = data.Parameters[249];
|
|
if (u255 && u255.user) {
|
|
parsePhotonUser(id255, u255.user, gameLogDate);
|
|
if (u255.avatarDict) {
|
|
parsePhotonAvatarChange(
|
|
id255,
|
|
u255.user,
|
|
u255.avatarDict,
|
|
gameLogDate
|
|
);
|
|
parsePhotonAvatar(u255.avatarDict);
|
|
}
|
|
if (u255.favatarDict) {
|
|
parsePhotonAvatar(u255.favatarDict);
|
|
}
|
|
if (typeof u255.groupOnNameplate !== 'undefined') {
|
|
parsePhotonGroupChange(
|
|
id255,
|
|
u255.user,
|
|
u255.groupOnNameplate,
|
|
gameLogDate
|
|
);
|
|
}
|
|
}
|
|
}
|
|
parsePhotonLobbyIds(data.Parameters[252]);
|
|
var hasInstantiated = false;
|
|
if (photonLobbyCurrentUser.value === id255) {
|
|
// fix current user
|
|
hasInstantiated = true;
|
|
}
|
|
var ref = photonLobbyCurrent.value.get(id255);
|
|
if (typeof ref !== 'undefined') {
|
|
// fix for join event firing twice
|
|
// fix instantiation happening out of order before join event
|
|
hasInstantiated = ref.hasInstantiated;
|
|
}
|
|
if (data.Parameters[249]) {
|
|
photonLobbyJointime.value.set(id255, {
|
|
joinTime: Date.parse(gameLogDate),
|
|
hasInstantiated,
|
|
inVRMode: data.Parameters[249].inVRMode,
|
|
avatarEyeHeight: data.Parameters[249].avatarEyeHeight,
|
|
canModerateInstance:
|
|
data.Parameters[249].canModerateInstance,
|
|
groupOnNameplate: data.Parameters[249].groupOnNameplate,
|
|
showGroupBadgeToOthers:
|
|
data.Parameters[249].showGroupBadgeToOthers,
|
|
showSocialRank: data.Parameters[249].showSocialRank,
|
|
useImpostorAsFallback:
|
|
data.Parameters[249].useImpostorAsFallback,
|
|
platform: data.Parameters[249].platform
|
|
});
|
|
photonUserJoin(id255, data.Parameters[249], gameLogDate);
|
|
}
|
|
startLobbyWatcherLoop();
|
|
break;
|
|
case 254:
|
|
// Leave
|
|
var photonId = data.Parameters[254];
|
|
photonUserLeave(photonId, gameLogDate);
|
|
photonLobbyCurrent.value.delete(photonId);
|
|
photonLobbyLastModeration.value.delete(photonId);
|
|
photonLobbyJointime.value.delete(photonId);
|
|
photonEvent7List.value.delete(photonId);
|
|
parsePhotonLobbyIds(data.Parameters[252]);
|
|
if (typeof data.Parameters[203] !== 'undefined') {
|
|
setPhotonLobbyMaster(data.Parameters[203], gameLogDate);
|
|
}
|
|
break;
|
|
case 4:
|
|
// Sync
|
|
setPhotonLobbyMaster(data.Parameters[254], gameLogDate);
|
|
break;
|
|
case 33:
|
|
// Moderation
|
|
if (data.Parameters[245]['0'] === 21) {
|
|
if (data.Parameters[245]['1']) {
|
|
var photonId = data.Parameters[245]['1'];
|
|
const block = data.Parameters[245]['10'];
|
|
const mute = data.Parameters[245]['11'];
|
|
var ref = photonLobby.value.get(photonId);
|
|
if (
|
|
typeof ref !== 'undefined' &&
|
|
typeof ref.id !== 'undefined'
|
|
) {
|
|
photonModerationUpdate(
|
|
ref,
|
|
photonId,
|
|
block,
|
|
mute,
|
|
gameLogDate
|
|
);
|
|
} else {
|
|
moderationEventQueue.value.set(photonId, {
|
|
block,
|
|
mute,
|
|
gameLogDate
|
|
});
|
|
}
|
|
} else {
|
|
const blockArray = data.Parameters[245]['10'];
|
|
const muteArray = data.Parameters[245]['11'];
|
|
const idList = new Map();
|
|
blockArray.forEach((photonId1) => {
|
|
if (muteArray.includes(photonId1)) {
|
|
idList.set(photonId1, {
|
|
isMute: true,
|
|
isBlock: true
|
|
});
|
|
} else {
|
|
idList.set(photonId1, {
|
|
isMute: false,
|
|
isBlock: true
|
|
});
|
|
}
|
|
});
|
|
muteArray.forEach((photonId2) => {
|
|
if (!idList.has(photonId2)) {
|
|
idList.set(photonId2, {
|
|
isMute: true,
|
|
isBlock: false
|
|
});
|
|
}
|
|
});
|
|
idList.forEach(({ isMute, isBlock }, photonId3) => {
|
|
const ref1 = photonLobby.value.get(photonId3);
|
|
if (
|
|
typeof ref1 !== 'undefined' &&
|
|
typeof ref1.id !== 'undefined'
|
|
) {
|
|
photonModerationUpdate(
|
|
ref1,
|
|
photonId3,
|
|
isBlock,
|
|
isMute,
|
|
gameLogDate
|
|
);
|
|
} else {
|
|
moderationEventQueue.value.set(photonId3, {
|
|
block: isBlock,
|
|
mute: isMute,
|
|
gameLogDate
|
|
});
|
|
}
|
|
});
|
|
}
|
|
} else if (
|
|
data.Parameters[245]['0'] === 13 ||
|
|
data.Parameters[245]['0'] === 25
|
|
) {
|
|
let msg = data.Parameters[245]['2'];
|
|
if (
|
|
typeof msg === 'string' &&
|
|
typeof data.Parameters[245]['14'] === 'object'
|
|
) {
|
|
for (let prop in data.Parameters[245]['14']) {
|
|
const value = data.Parameters[245]['14'][prop];
|
|
msg = msg.replace(`{{${prop}}}`, value);
|
|
}
|
|
}
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text: msg,
|
|
type: 'Moderation',
|
|
color: 'yellow',
|
|
created_at: gameLogDate
|
|
});
|
|
}
|
|
break;
|
|
case 202:
|
|
// Instantiate
|
|
if (!photonLobby.value.has(data.Parameters[254])) {
|
|
photonLobby.value.set(data.Parameters[254]);
|
|
}
|
|
if (!photonLobbyCurrent.value.has(data.Parameters[254])) {
|
|
photonLobbyCurrent.value.set(data.Parameters[254]);
|
|
}
|
|
var lobbyJointime = photonLobbyJointime.value.get(
|
|
data.Parameters[254]
|
|
);
|
|
if (typeof lobbyJointime !== 'undefined') {
|
|
photonLobbyJointime.value.set(data.Parameters[254], {
|
|
...lobbyJointime,
|
|
hasInstantiated: true
|
|
});
|
|
} else {
|
|
photonLobbyJointime.value.set(data.Parameters[254], {
|
|
joinTime: Date.parse(gameLogDate),
|
|
hasInstantiated: true
|
|
});
|
|
}
|
|
break;
|
|
case 43:
|
|
// Chatbox Message
|
|
var photonId = data.Parameters[254];
|
|
var text = data.Parameters[245];
|
|
if (photonLobbyCurrentUser.value === photonId) {
|
|
return;
|
|
}
|
|
const lastMsg = photonLastChatBoxMsg.value.get(photonId);
|
|
if (lastMsg === text) {
|
|
return;
|
|
}
|
|
photonLastChatBoxMsg.value.set(photonId, text);
|
|
var userId = getUserIdFromPhotonId(photonId);
|
|
if (
|
|
chatboxUserBlacklist.value.has(userId) ||
|
|
checkChatboxBlacklist(text)
|
|
) {
|
|
return;
|
|
}
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text,
|
|
type: 'ChatBoxMessage',
|
|
created_at: gameLogDate
|
|
});
|
|
const entry = {
|
|
userId,
|
|
displayName: getDisplayNameFromPhotonId(photonId),
|
|
created_at: gameLogDate,
|
|
type: 'ChatBoxMessage',
|
|
text
|
|
};
|
|
notificationStore.queueGameLogNoty(entry);
|
|
gameLogStore.addGameLog(entry);
|
|
break;
|
|
case 70:
|
|
// Portal Spawn
|
|
if (data.Parameters[245][0] === 20) {
|
|
const portalId = data.Parameters[245][1];
|
|
const portalUserId = data.Parameters[245][2];
|
|
const shortName = data.Parameters[245][5];
|
|
const portalWorldName = data.Parameters[245][8].name;
|
|
addPhotonPortalSpawn(
|
|
gameLogDate,
|
|
portalUserId,
|
|
shortName,
|
|
portalWorldName
|
|
);
|
|
photonLobbyActivePortals.value.set(portalId, {
|
|
userId: portalUserId,
|
|
shortName,
|
|
worldName: portalWorldName,
|
|
created_at: Date.parse(gameLogDate),
|
|
pendingLeave: 0
|
|
});
|
|
} else if (data.Parameters[245][0] === 21) {
|
|
const portalId = data.Parameters[245][1];
|
|
const portalUserId = data.Parameters[245][2];
|
|
const playerCount = data.Parameters[245][3];
|
|
const shortName = data.Parameters[245][5];
|
|
const portalWorldName = '';
|
|
addPhotonPortalSpawn(
|
|
gameLogDate,
|
|
portalUserId,
|
|
shortName,
|
|
portalWorldName
|
|
);
|
|
photonLobbyActivePortals.value.set(portalId, {
|
|
userId: portalUserId,
|
|
shortName,
|
|
worldName: portalWorldName,
|
|
created_at: Date.parse(gameLogDate),
|
|
playerCount: 0,
|
|
pendingLeave: 0
|
|
});
|
|
} else if (data.Parameters[245][0] === 22) {
|
|
const portalId = data.Parameters[245][1];
|
|
let portalText = 'DeletedPortal';
|
|
const ref = photonLobbyActivePortals.value.get(portalId);
|
|
if (typeof ref !== 'undefined') {
|
|
const portalWorldName = ref.worldName;
|
|
const playerCount = ref.playerCount;
|
|
const time = timeToText(
|
|
Date.parse(gameLogDate) - ref.created_at
|
|
);
|
|
portalText = `DeletedPortal after ${time} with ${playerCount} players to "${portalWorldName}"`;
|
|
}
|
|
addEntryPhotonEvent({
|
|
text: portalText,
|
|
type: 'DeletedPortal',
|
|
created_at: gameLogDate
|
|
});
|
|
photonLobbyActivePortals.value.delete(portalId);
|
|
} else if (data.Parameters[245][0] === 23) {
|
|
const portalId = data.Parameters[245][1];
|
|
const playerCount = data.Parameters[245][3];
|
|
const ref = photonLobbyActivePortals.value.get(portalId);
|
|
if (typeof ref !== 'undefined') {
|
|
ref.pendingLeave++;
|
|
ref.playerCount = playerCount;
|
|
}
|
|
} else if (data.Parameters[245][0] === 24) {
|
|
addEntryPhotonEvent({
|
|
text: 'PortalError failed to create portal',
|
|
type: 'DeletedPortal',
|
|
created_at: gameLogDate
|
|
});
|
|
}
|
|
break;
|
|
case 71:
|
|
// Spawn Emoji
|
|
var photonId = data.Parameters[254];
|
|
if (photonId === photonLobbyCurrentUser.value) {
|
|
return;
|
|
}
|
|
const type = data.Parameters[245][0];
|
|
let emojiName = '';
|
|
let imageUrl = '';
|
|
if (type === 0) {
|
|
const emojiId = data.Parameters[245][2];
|
|
emojiName = photonEmojis[emojiId];
|
|
} else if (type === 1) {
|
|
emojiName = 'Custom';
|
|
var fileId = data.Parameters[245][1];
|
|
imageUrl = `${AppDebug.endpointDomain}/file/${fileId}/1/`;
|
|
}
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text: emojiName,
|
|
type: 'SpawnEmoji',
|
|
created_at: gameLogDate,
|
|
imageUrl,
|
|
fileId
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
function parseVRCEvent(json) {
|
|
// VRC Event
|
|
const datetime = json.dt;
|
|
const eventData = json.VRCEventData;
|
|
const senderId = eventData.Sender;
|
|
if (AppDebug.debugPhotonLogging) {
|
|
console.log('VrcEvent:', json);
|
|
}
|
|
if (eventData.EventName === '_SendOnSpawn') {
|
|
return;
|
|
} else if (eventData.EventType > 34) {
|
|
const entry = {
|
|
created_at: datetime,
|
|
type: 'Event',
|
|
data: `${getDisplayNameFromPhotonId(
|
|
senderId
|
|
)} called non existent RPC ${eventData.EventType}`
|
|
};
|
|
addPhotonEventToGameLog(entry);
|
|
return;
|
|
}
|
|
if (eventData.EventType === 14) {
|
|
let type = 'Event';
|
|
if (eventData.EventName === 'ChangeVisibility') {
|
|
if (eventData.Data[0] === true) {
|
|
var text = 'EnableCamera';
|
|
} else if (eventData.Data[0] === false) {
|
|
var text = 'DisableCamera';
|
|
}
|
|
type = 'Camera';
|
|
} else if (eventData.EventName === 'PhotoCapture') {
|
|
var text = 'PhotoCapture';
|
|
type = 'Camera';
|
|
} else if (eventData.EventName === 'TimerBloop') {
|
|
var text = 'TimerBloop';
|
|
type = 'Camera';
|
|
} else if (eventData.EventName === 'ReloadAvatarNetworkedRPC') {
|
|
var text = 'AvatarReset';
|
|
} else if (eventData.EventName === 'ReleaseBones') {
|
|
var text = 'ResetPhysBones';
|
|
} else if (eventData.EventName === 'SpawnEmojiRPC') {
|
|
// var text = this.oldPhotonEmojis[eventData.Data];
|
|
type = 'SpawnEmoji';
|
|
} else {
|
|
let eventVrc = '';
|
|
if (eventData.Data && eventData.Data.length > 0) {
|
|
eventVrc = ` ${JSON.stringify(eventData.Data).replace(
|
|
/"([^(")"]+)":/g,
|
|
'$1:'
|
|
)}`;
|
|
}
|
|
var text = `${eventData.EventName}${eventVrc}`;
|
|
}
|
|
addEntryPhotonEvent({
|
|
photonId: senderId,
|
|
text,
|
|
type,
|
|
created_at: datetime
|
|
});
|
|
} else {
|
|
let eventName = '';
|
|
if (eventData.EventName) {
|
|
eventName = ` ${JSON.stringify(eventData.EventName).replace(
|
|
/"([^(")"]+)":/g,
|
|
'$1:'
|
|
)}`;
|
|
}
|
|
if (AppDebug.debugPhotonLogging) {
|
|
const displayName = getDisplayNameFromPhotonId(senderId);
|
|
const feed = `RPC ${displayName} ${
|
|
photonEventType[eventData.EventType]
|
|
}${eventName}`;
|
|
console.log('VrcRpc:', feed);
|
|
}
|
|
}
|
|
}
|
|
|
|
// async function parsePhotonPortalSpawn(
|
|
// created_at,
|
|
// instanceId,
|
|
// ref,
|
|
// portalType,
|
|
// shortName,
|
|
// photonId
|
|
// ) {
|
|
// let worldName = shortName;
|
|
// if (instanceId) {
|
|
// worldName = await getWorldName(instanceId);
|
|
// }
|
|
// addEntryPhotonEvent({
|
|
// photonId,
|
|
// text: `${portalType} PortalSpawn to ${worldName}`,
|
|
// type: 'PortalSpawn',
|
|
// shortName,
|
|
// location: instanceId,
|
|
// worldName,
|
|
// created_at
|
|
// });
|
|
// addPhotonEventToGameLog({
|
|
// created_at,
|
|
// type: 'PortalSpawn',
|
|
// displayName: ref.displayName,
|
|
// location: locationStore.lastLocation.location,
|
|
// userId: ref.id,
|
|
// instanceId,
|
|
// worldName
|
|
// });
|
|
// }
|
|
|
|
async function addPhotonPortalSpawn(
|
|
gameLogDate,
|
|
userId,
|
|
shortName,
|
|
worldName
|
|
) {
|
|
const instance = await instanceRequest.getInstanceFromShortName({
|
|
shortName
|
|
});
|
|
const location = instance.json.location;
|
|
const L = parseLocation(location);
|
|
let groupName = '';
|
|
if (L.groupId) {
|
|
groupName = await getGroupName(L.groupId);
|
|
}
|
|
if (!worldName) {
|
|
worldName = await getWorldName(location);
|
|
}
|
|
// var newShortName = instance.json.shortName;
|
|
// var portalType = 'Secure';
|
|
// if (shortName === newShortName) {
|
|
// portalType = 'Unlocked';
|
|
// }
|
|
const _displayLocation = displayLocation(
|
|
location,
|
|
worldName,
|
|
groupName
|
|
);
|
|
addEntryPhotonEvent({
|
|
photonId: getPhotonIdFromUserId(userId),
|
|
text: `PortalSpawn to ${_displayLocation}`,
|
|
type: 'PortalSpawn',
|
|
shortName,
|
|
location,
|
|
worldName,
|
|
groupName,
|
|
created_at: gameLogDate
|
|
});
|
|
addPhotonEventToGameLog({
|
|
created_at: gameLogDate,
|
|
type: 'PortalSpawn',
|
|
displayName: getDisplayName(userId),
|
|
location: locationStore.lastLocation.location,
|
|
userId,
|
|
instanceId: location,
|
|
worldName,
|
|
groupName
|
|
});
|
|
}
|
|
|
|
function addPhotonEventToGameLog(entry) {
|
|
notificationStore.queueGameLogNoty(entry);
|
|
gameLogStore.addGameLog(entry);
|
|
if (entry.type === 'PortalSpawn') {
|
|
database.addGamelogPortalSpawnToDatabase(entry);
|
|
} else if (entry.type === 'Event') {
|
|
database.addGamelogEventToDatabase(entry);
|
|
}
|
|
}
|
|
|
|
function parsePhotonLobbyIds(lobbyIds) {
|
|
if (!Array.isArray(lobbyIds)) {
|
|
return;
|
|
}
|
|
lobbyIds.forEach((id) => {
|
|
if (!photonLobby.value.has(id)) {
|
|
photonLobby.value.set(id);
|
|
}
|
|
if (!photonLobbyCurrent.value.has(id)) {
|
|
photonLobbyCurrent.value.set(id);
|
|
}
|
|
});
|
|
for (var id of photonLobbyCurrent.value.keys()) {
|
|
if (!lobbyIds.includes(id)) {
|
|
photonLobbyCurrent.value.delete(id);
|
|
photonEvent7List.value.delete(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
function setPhotonLobbyMaster(photonId, gameLogDate) {
|
|
if (photonLobbyMaster.value !== photonId) {
|
|
if (photonLobbyMaster.value !== 0) {
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text: `Photon Master Migrate`,
|
|
type: 'MasterMigrate',
|
|
created_at: gameLogDate
|
|
});
|
|
}
|
|
photonLobbyMaster.value = photonId;
|
|
}
|
|
}
|
|
|
|
async function parsePhotonUser(photonId, user, gameLogDate) {
|
|
if (typeof user === 'undefined') {
|
|
console.error('PhotonUser: user is undefined', photonId);
|
|
return;
|
|
}
|
|
let tags = [];
|
|
if (typeof user.tags !== 'undefined') {
|
|
tags = user.tags;
|
|
}
|
|
let ref = userStore.cachedUsers.get(user.id);
|
|
const photonUser = {
|
|
id: user.id,
|
|
displayName: user.displayName,
|
|
developerType: user.developerType,
|
|
profilePicOverride: user.profilePicOverride,
|
|
currentAvatarImageUrl: user.currentAvatarImageUrl,
|
|
currentAvatarThumbnailImageUrl: user.currentAvatarThumbnailImageUrl,
|
|
userIcon: user.userIcon,
|
|
last_platform: user.last_platform,
|
|
allowAvatarCopying: user.allowAvatarCopying,
|
|
status: user.status,
|
|
statusDescription: user.statusDescription,
|
|
bio: user.bio,
|
|
tags
|
|
};
|
|
photonLobby.value.set(photonId, photonUser);
|
|
photonLobbyCurrent.value.set(photonId, photonUser);
|
|
photonLobbyUserDataUpdate(photonId, photonUser, gameLogDate);
|
|
|
|
const bias = Date.parse(gameLogDate) + 60 * 1000; // 1min
|
|
if (bias > Date.now()) {
|
|
if (typeof ref === 'undefined' || typeof ref.id === 'undefined') {
|
|
try {
|
|
const args = await userRequest.getUser({
|
|
userId: user.id
|
|
});
|
|
ref = args.ref;
|
|
} catch (err) {
|
|
console.error(err);
|
|
ref = photonUser;
|
|
}
|
|
} else if (
|
|
!ref.isFriend &&
|
|
locationStore.lastLocation.playerList.has(user.id)
|
|
) {
|
|
let { joinTime } = locationStore.lastLocation.playerList.get(
|
|
user.id
|
|
);
|
|
if (!joinTime) {
|
|
joinTime = Date.parse(gameLogDate);
|
|
}
|
|
ref.$location_at = joinTime;
|
|
ref.$online_for = joinTime;
|
|
}
|
|
if (
|
|
typeof ref.id !== 'undefined' &&
|
|
ref.currentAvatarImageUrl !== user.currentAvatarImageUrl
|
|
) {
|
|
userStore.applyUser({
|
|
...ref,
|
|
currentAvatarImageUrl: user.currentAvatarImageUrl,
|
|
currentAvatarThumbnailImageUrl:
|
|
user.currentAvatarThumbnailImageUrl
|
|
});
|
|
}
|
|
}
|
|
if (typeof ref !== 'undefined' && typeof ref.id !== 'undefined') {
|
|
photonLobby.value.set(photonId, ref);
|
|
photonLobbyCurrent.value.set(photonId, ref);
|
|
// check moderation queue
|
|
if (moderationEventQueue.value.has(photonId)) {
|
|
var { block, mute, gameLogDate } =
|
|
moderationEventQueue.value.get(photonId);
|
|
moderationEventQueue.value.delete(photonId);
|
|
photonModerationUpdate(ref, photonId, block, mute, gameLogDate);
|
|
}
|
|
}
|
|
}
|
|
|
|
function photonLobbyUserDataUpdate(photonId, photonUser, gameLogDate) {
|
|
const ref = photonLobbyUserData.value.get(photonId);
|
|
if (
|
|
typeof ref !== 'undefined' &&
|
|
photonId !== photonLobbyCurrentUser.value &&
|
|
(photonUser.status !== ref.status ||
|
|
photonUser.statusDescription !== ref.statusDescription)
|
|
) {
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
type: 'ChangeStatus',
|
|
status: photonUser.status,
|
|
previousStatus: ref.status,
|
|
statusDescription: replaceBioSymbols(
|
|
photonUser.statusDescription
|
|
),
|
|
previousStatusDescription: replaceBioSymbols(
|
|
ref.statusDescription
|
|
),
|
|
created_at: Date.parse(gameLogDate)
|
|
});
|
|
}
|
|
photonLobbyUserData.value.set(photonId, photonUser);
|
|
}
|
|
|
|
function photonUserJoin(photonId, user, gameLogDate) {
|
|
if (photonId === photonLobbyCurrentUser.value) {
|
|
return;
|
|
}
|
|
const avatar = user.avatarDict;
|
|
avatar.name = replaceBioSymbols(avatar.name);
|
|
avatar.description = replaceBioSymbols(avatar.description);
|
|
let platform = '';
|
|
if (user.last_platform === 'android') {
|
|
platform = 'Android';
|
|
} else if (user.last_platform === 'ios') {
|
|
platform = 'iOS';
|
|
} else if (user.inVRMode) {
|
|
platform = 'VR';
|
|
} else {
|
|
platform = 'Desktop';
|
|
}
|
|
photonUserSusieCheck(photonId, user, gameLogDate);
|
|
checkVRChatCache(avatar).then((cacheInfo) => {
|
|
let inCache = false;
|
|
if (cacheInfo.Item1 > 0) {
|
|
inCache = true;
|
|
}
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text: 'has joined',
|
|
type: 'OnPlayerJoined',
|
|
created_at: gameLogDate,
|
|
avatar,
|
|
inCache,
|
|
platform
|
|
});
|
|
});
|
|
}
|
|
|
|
function photonUserSusieCheck(photonId, user, gameLogDate) {
|
|
let text = '';
|
|
if (typeof user.modTag !== 'undefined') {
|
|
text = `Moderator has joined ${user.modTag}`;
|
|
} else if (user.isInvisible) {
|
|
text = 'User joined invisible';
|
|
}
|
|
if (text) {
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text,
|
|
type: 'Event',
|
|
color: 'yellow',
|
|
created_at: gameLogDate
|
|
});
|
|
const entry = {
|
|
created_at: new Date().toJSON(),
|
|
type: 'Event',
|
|
data: `${text} - ${getDisplayNameFromPhotonId(
|
|
photonId
|
|
)} (${getUserIdFromPhotonId(photonId)})`
|
|
};
|
|
notificationStore.queueGameLogNoty(entry);
|
|
gameLogStore.addGameLog(entry);
|
|
database.addGamelogEventToDatabase(entry);
|
|
}
|
|
}
|
|
|
|
function photonUserLeave(photonId, gameLogDate) {
|
|
if (!photonLobbyCurrent.value.has(photonId)) {
|
|
return;
|
|
}
|
|
let text = 'has left';
|
|
const lastEvent = photonEvent7List.value.get(parseInt(photonId, 10));
|
|
if (typeof lastEvent !== 'undefined') {
|
|
const timeSinceLastEvent = Date.now() - Date.parse(lastEvent);
|
|
if (timeSinceLastEvent > 10 * 1000) {
|
|
// 10 seconds
|
|
text = `has timed out after ${timeToText(timeSinceLastEvent)}`;
|
|
}
|
|
}
|
|
photonLobbyActivePortals.value.forEach((portal) => {
|
|
if (portal.pendingLeave > 0) {
|
|
text = `has left through portal to "${portal.worldName}"`;
|
|
portal.pendingLeave--;
|
|
}
|
|
});
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text,
|
|
type: 'OnPlayerLeft',
|
|
created_at: gameLogDate
|
|
});
|
|
}
|
|
|
|
function photonModerationUpdate(ref, photonId, block, mute, gameLogDate) {
|
|
database.getModeration(ref.id).then((row) => {
|
|
const lastType = photonLobbyLastModeration.value.get(photonId);
|
|
let type = '';
|
|
let text = '';
|
|
if (block) {
|
|
type = 'Blocked';
|
|
text = 'Blocked';
|
|
} else if (mute) {
|
|
type = 'Muted';
|
|
text = 'Muted';
|
|
}
|
|
if (row.userId) {
|
|
if (!block && row.block) {
|
|
type = 'Unblocked';
|
|
text = 'Unblocked';
|
|
} else if (!mute && row.mute) {
|
|
type = 'Unmuted';
|
|
text = 'Unmuted';
|
|
}
|
|
if (block === row.block && mute === row.mute) {
|
|
// no change
|
|
if (type && type !== lastType) {
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text: `Moderation ${text}`,
|
|
type: 'Moderation',
|
|
color: 'yellow',
|
|
created_at: gameLogDate
|
|
});
|
|
}
|
|
photonLobbyLastModeration.value.set(photonId, type);
|
|
return;
|
|
}
|
|
}
|
|
photonLobbyLastModeration.value.set(photonId, type);
|
|
moderationAgainstTable.value.forEach((item) => {
|
|
if (item.userId === ref.id && item.type === type) {
|
|
removeFromArray(moderationAgainstTable.value, item);
|
|
}
|
|
});
|
|
if (type) {
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
text: `Moderation ${text}`,
|
|
type: 'Moderation',
|
|
color: 'yellow',
|
|
created_at: gameLogDate
|
|
});
|
|
const noty = {
|
|
created_at: new Date().toJSON(),
|
|
userId: ref.id,
|
|
displayName: ref.displayName,
|
|
type
|
|
};
|
|
notificationStore.queueModerationNoty(noty);
|
|
const entry = {
|
|
created_at: gameLogDate,
|
|
userId: ref.id,
|
|
displayName: ref.displayName,
|
|
type
|
|
};
|
|
moderationAgainstTable.value.push(entry);
|
|
}
|
|
if (block || mute || block !== row.block || mute !== row.mute) {
|
|
sharedFeedStore.updateSharedFeed(true);
|
|
}
|
|
if (block || mute) {
|
|
database.setModeration({
|
|
userId: ref.id,
|
|
updatedAt: gameLogDate,
|
|
displayName: ref.displayName,
|
|
block,
|
|
mute
|
|
});
|
|
} else if (row.block || row.mute) {
|
|
database.deleteModeration(ref.id);
|
|
}
|
|
});
|
|
}
|
|
|
|
function parsePhotonAvatarChange(photonId, user, avatar, gameLogDate) {
|
|
if (typeof avatar === 'undefined') {
|
|
return;
|
|
}
|
|
if (typeof user === 'undefined') {
|
|
console.error('PhotonAvatarChange: user is undefined', photonId);
|
|
return;
|
|
}
|
|
const oldAvatarId = photonLobbyAvatars.value.get(user.id);
|
|
if (
|
|
oldAvatarId &&
|
|
oldAvatarId !== avatar.id &&
|
|
photonId !== photonLobbyCurrentUser.value
|
|
) {
|
|
avatar.name = replaceBioSymbols(avatar.name);
|
|
avatar.description = replaceBioSymbols(avatar.description);
|
|
checkVRChatCache(avatar).then((cacheInfo) => {
|
|
let inCache = false;
|
|
if (cacheInfo.Item1 > 0) {
|
|
inCache = true;
|
|
}
|
|
const entry = {
|
|
created_at: new Date().toJSON(),
|
|
type: 'AvatarChange',
|
|
userId: user.id,
|
|
displayName: user.displayName,
|
|
name: avatar.name,
|
|
description: avatar.description,
|
|
avatarId: avatar.id,
|
|
authorId: avatar.authorId,
|
|
releaseStatus: avatar.releaseStatus,
|
|
imageUrl: avatar.imageUrl,
|
|
thumbnailImageUrl: avatar.thumbnailImageUrl
|
|
};
|
|
notificationStore.queueGameLogNoty(entry);
|
|
gameLogStore.addGameLog(entry);
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
displayName: user.displayName,
|
|
userId: user.id,
|
|
text: `ChangeAvatar ${avatar.name}`,
|
|
type: 'ChangeAvatar',
|
|
created_at: gameLogDate,
|
|
avatar,
|
|
inCache
|
|
});
|
|
});
|
|
}
|
|
photonLobbyAvatars.value.set(user.id, avatar.id);
|
|
}
|
|
|
|
async function parsePhotonGroupChange(
|
|
photonId,
|
|
user,
|
|
groupId,
|
|
gameLogDate
|
|
) {
|
|
if (
|
|
typeof user === 'undefined' ||
|
|
!photonLobbyJointime.value.has(photonId)
|
|
) {
|
|
return;
|
|
}
|
|
let { groupOnNameplate } = photonLobbyJointime.value.get(photonId);
|
|
if (
|
|
typeof groupOnNameplate !== 'undefined' &&
|
|
groupOnNameplate !== groupId &&
|
|
photonId !== photonLobbyCurrentUser.value
|
|
) {
|
|
const groupName = await getGroupName(groupId);
|
|
const previousGroupName = await getGroupName(groupOnNameplate);
|
|
addEntryPhotonEvent({
|
|
photonId,
|
|
displayName: user.displayName,
|
|
userId: user.id,
|
|
text: `ChangeGroup ${groupName}`,
|
|
type: 'ChangeGroup',
|
|
created_at: gameLogDate,
|
|
groupId,
|
|
groupName,
|
|
previousGroupId: groupOnNameplate,
|
|
previousGroupName
|
|
});
|
|
}
|
|
}
|
|
|
|
function parsePhotonAvatar(avatar) {
|
|
if (typeof avatar === 'undefined' || typeof avatar.id === 'undefined') {
|
|
console.warn('PhotonAvatar: avatar is undefined');
|
|
return;
|
|
}
|
|
let tags = [];
|
|
let unityPackages = [];
|
|
if (typeof avatar.tags !== 'undefined') {
|
|
tags = avatar.tags;
|
|
}
|
|
if (typeof avatar.unityPackages !== 'undefined') {
|
|
unityPackages = avatar.unityPackages;
|
|
}
|
|
if (!avatar.assetUrl && unityPackages.length > 0) {
|
|
for (const unityPackage of unityPackages) {
|
|
if (
|
|
unityPackage.variant &&
|
|
unityPackage.variant !== 'standard' &&
|
|
unityPackage.variant !== 'security'
|
|
) {
|
|
continue;
|
|
}
|
|
if (unityPackage.platform === 'standalonewindows') {
|
|
avatar.assetUrl = unityPackage.assetUrl;
|
|
}
|
|
}
|
|
}
|
|
avatarStore.applyAvatar({
|
|
id: avatar.id,
|
|
authorId: avatar.authorId,
|
|
authorName: avatar.authorName,
|
|
updated_at: avatar.updated_at,
|
|
description: avatar.description,
|
|
imageUrl: avatar.imageUrl,
|
|
thumbnailImageUrl: avatar.thumbnailImageUrl,
|
|
name: avatar.name,
|
|
releaseStatus: avatar.releaseStatus,
|
|
version: avatar.version,
|
|
tags,
|
|
unityPackages
|
|
});
|
|
}
|
|
|
|
function safeParseInt(val) {
|
|
const n = parseInt(val, 10);
|
|
return Number.isFinite(n) ? n : null;
|
|
}
|
|
|
|
return {
|
|
state,
|
|
|
|
photonLoggingEnabled,
|
|
photonEventOverlay,
|
|
photonEventOverlayFilter,
|
|
photonEventTableTypeOverlayFilter,
|
|
timeoutHudOverlay,
|
|
timeoutHudOverlayFilter,
|
|
photonEventIcon,
|
|
photonLobbyTimeoutThreshold,
|
|
photonOverlayMessageTimeout,
|
|
photonEventTableTypeFilter,
|
|
photonEventTable,
|
|
photonEventTablePrevious,
|
|
chatboxUserBlacklist,
|
|
chatboxBlacklist,
|
|
photonEventTableFilter,
|
|
photonLobby,
|
|
photonLobbyMaster,
|
|
photonLobbyCurrentUser,
|
|
photonLobbyUserData,
|
|
photonLobbyCurrent,
|
|
photonLobbyAvatars,
|
|
photonLobbyLastModeration,
|
|
photonLobbyTimeout,
|
|
photonLobbyJointime,
|
|
photonLobbyActivePortals,
|
|
photonEvent7List,
|
|
photonLastEvent7List,
|
|
photonLastChatBoxMsg,
|
|
moderationEventQueue,
|
|
|
|
setPhotonLoggingEnabled,
|
|
setPhotonEventOverlay,
|
|
setPhotonEventOverlayFilter,
|
|
setPhotonEventTableTypeOverlayFilter,
|
|
setTimeoutHudOverlay,
|
|
setTimeoutHudOverlayFilter,
|
|
getDisplayName,
|
|
photonEventPulse,
|
|
parseOperationResponse,
|
|
saveEventOverlay,
|
|
checkChatboxBlacklist,
|
|
saveChatboxUserBlacklist,
|
|
saveChatboxBlacklist,
|
|
photonEventTableFilterChange,
|
|
showUserFromPhotonId,
|
|
promptPhotonOverlayMessageTimeout,
|
|
promptPhotonLobbyTimeoutThreshold,
|
|
photonLobbyWatcherLoopStop,
|
|
parsePhotonEvent,
|
|
parseVRCEvent,
|
|
moderationAgainstTable
|
|
};
|
|
});
|