diff --git a/html/src/app.js b/html/src/app.js index 66fdafee..f2eabae6 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -5237,13 +5237,27 @@ speechSynthesis.getVoices(); ); break; case 'PortalSpawn': - this.speak('User has spawned a portal'); + if (noty.displayName) { + this.speak( + `${ + noty.displayName + } has spawned a portal to ${this.displayLocation( + noty.instanceId, + noty.worldName + )}` + ); + } else { + this.speak('User has spawned a portal'); + } break; case 'AvatarChange': this.speak( `${noty.displayName} changed into avatar ${noty.name}` ); break; + case 'ChatBoxMessage': + this.speak(`${noty.displayName} said ${noty.text}`); + break; case 'Event': this.speak(noty.data); break; @@ -5424,12 +5438,26 @@ speechSynthesis.getVoices(); ); break; case 'PortalSpawn': - AppApi.XSNotification( - 'VRCX', - 'User has spawned a portal', - timeout, - image - ); + if (noty.displayName) { + AppApi.XSNotification( + 'VRCX', + `${ + noty.displayName + } has spawned a portal to ${this.displayLocation( + noty.instanceId, + noty.worldName + )}`, + timeout, + image + ); + } else { + AppApi.XSNotification( + 'VRCX', + 'User has spawned a portal', + timeout, + image + ); + } break; case 'AvatarChange': AppApi.XSNotification( @@ -5439,6 +5467,14 @@ speechSynthesis.getVoices(); image ); break; + case 'ChatBoxMessage': + AppApi.XSNotification( + 'VRCX', + `${noty.displayName} said ${noty.text}`, + timeout, + image + ); + break; case 'Event': AppApi.XSNotification('VRCX', noty.data, timeout, image); break; @@ -5641,11 +5677,22 @@ speechSynthesis.getVoices(); ); break; case 'PortalSpawn': - AppApi.DesktopNotification( - noty.displayName, - 'User has spawned a portal', - image - ); + if (noty.displayName) { + AppApi.DesktopNotification( + noty.displayName, + `has spawned a portal to ${this.displayLocation( + noty.instanceId, + noty.worldName + )}`, + image + ); + } else { + AppApi.DesktopNotification( + '', + 'User has spawned a portal', + image + ); + } break; case 'AvatarChange': AppApi.DesktopNotification( @@ -5654,6 +5701,13 @@ speechSynthesis.getVoices(); image ); break; + case 'ChatBoxMessage': + AppApi.DesktopNotification( + noty.displayName, + `said ${noty.text}`, + image + ); + break; case 'Event': AppApi.DesktopNotification('Event', noty.data, image); break; @@ -8131,6 +8185,7 @@ speechSynthesis.getVoices(); if ( entry.type === 'LocationDestination' || entry.type === 'AvatarChange' || + entry.type === 'ChatBoxMessage' || (entry.userId === API.currentUser.id && (entry.type === 'OnPlayerJoined' || entry.type === 'OnPlayerLeft')) @@ -8788,11 +8843,22 @@ speechSynthesis.getVoices(); }; $app.data.photonEventTableFilter = ''; + $app.data.photonEventTableTypeFilter = []; $app.methods.photonEventTableFilterChange = function () { this.photonEventTable.filters[0].value = this.photonEventTableFilter; + this.photonEventTable.filters[1].value = + this.photonEventTableTypeFilter; + this.photonEventTablePrevious.filters[0].value = this.photonEventTableFilter; + this.photonEventTablePrevious.filters[1].value = + this.photonEventTableTypeFilter; + + configRepository.setString( + 'VRCX_photonEventTypeFilter', + JSON.stringify(this.photonEventTableTypeFilter) + ); }; $app.data.photonEventTable = { @@ -8801,6 +8867,12 @@ speechSynthesis.getVoices(); { prop: ['displayName', 'text'], value: '' + }, + { + prop: 'type', + value: [], + filterFn: (row, filter) => + filter.value.some((v) => v === row.type) } ], tableProps: { @@ -8821,6 +8893,12 @@ speechSynthesis.getVoices(); { prop: ['displayName', 'text'], value: '' + }, + { + prop: 'type', + value: [], + filterFn: (row, filter) => + filter.value.some((v) => v === row.type) } ], tableProps: { @@ -8847,6 +8925,12 @@ speechSynthesis.getVoices(); ...input }; this.photonEventTable.data.unshift(feed); + if ( + this.photonEventTableTypeFilter.length > 0 && + !this.photonEventTableTypeFilter.includes(feed.type) + ) { + return; + } if (this.photonEventOverlay) { if ( this.photonEventOverlayFilter === 'VIP' || @@ -8945,221 +9029,256 @@ speechSynthesis.getVoices(); }; $app.methods.parsePhotonEvent = function (data, gameLogDate) { - if (data.Code === 253) { - // SetUserProperties - if (data.Parameters[253] === -1) { - for (var i in data.Parameters[251]) { - var id = parseInt(i, 10); - var user = data.Parameters[251][i]; - this.parsePhotonUser(id, user.user, gameLogDate); - this.parsePhotonAvatarChange( - id, - user.user, - user.avatarDict, - gameLogDate - ); - this.parsePhotonAvatar(user.avatarDict); - this.parsePhotonAvatar(user.favatarDict); - if (typeof user.inVRMode !== 'undefined') { - this.photonLobbyInVrMode.set(id, user.inVRMode); - } - this.photonLobbyJointime.set(id, { - joinTime: Date.parse(gameLogDate), - hasInstantiated: false, - inVRMode: user.inVRMode, - avatarEyeHeight: user.avatarEyeHeight - }); - } - } else { - this.parsePhotonUser( - data.Parameters[253], - data.Parameters[251].user, - gameLogDate - ); - this.parsePhotonAvatarChange( - data.Parameters[253], - data.Parameters[251].user, - data.Parameters[251].avatarDict, - gameLogDate - ); - this.parsePhotonAvatar(data.Parameters[251].avatarDict); - this.parsePhotonAvatar(data.Parameters[251].favatarDict); - if (typeof data.Parameters[251].inVRMode !== 'undefined') { - this.photonLobbyInVrMode.set( - data.Parameters[253], - data.Parameters[251].inVRMode - ); - } - } - } else if (data.Code === 42) { - // SetUserProperties - this.parsePhotonUser( - data.Parameters[254], - data.Parameters[245].user, - gameLogDate - ); - this.parsePhotonAvatarChange( - data.Parameters[254], - data.Parameters[245].user, - data.Parameters[245].avatarDict, - gameLogDate - ); - this.parsePhotonAvatar(data.Parameters[245].avatarDict); - this.parsePhotonAvatar(data.Parameters[245].favatarDict); - if (typeof data.Parameters[245].inVRMode !== 'undefined') { - this.photonLobbyInVrMode.set( - data.Parameters[254], - data.Parameters[245].inVRMode - ); - } - } else if (data.Code === 255) { - // Join - if (typeof data.Parameters[249] !== 'undefined') { - this.parsePhotonUser( - data.Parameters[254], - data.Parameters[249].user, - gameLogDate - ); - this.parsePhotonAvatarChange( - data.Parameters[254], - data.Parameters[249].user, - data.Parameters[249].avatarDict, - gameLogDate - ); - this.parsePhotonAvatar(data.Parameters[249].avatarDict); - this.parsePhotonAvatar(data.Parameters[249].favatarDict); - } - if (typeof data.Parameters[249].inVRMode !== 'undefined') { - this.photonLobbyInVrMode.set( - data.Parameters[254], - data.Parameters[249].inVRMode - ); - } - this.parsePhotonLobbyIds(data.Parameters[252]); - var hasInstantiated = false; - if (this.photonLobbyCurrentUser === data.Parameters[254]) { - hasInstantiated = true; - } - this.photonLobbyJointime.set(data.Parameters[254], { - joinTime: Date.parse(gameLogDate), - hasInstantiated, - inVRMode: data.Parameters[249].inVRMode, - avatarEyeHeight: data.Parameters[249].avatarEyeHeight - }); - var ref = this.photonLobbyCurrent.get(data.Parameters[254]); - this.photonUserJoin(data.Parameters[254], ref, gameLogDate); - this.checkPhotonBotJoin( - data.Parameters[254], - data.Parameters[249], - gameLogDate - ); - this.startLobbyWatcherLoop(); - } else if (data.Code === 254) { - // Leave - this.checkPhotonBotLeave(data.Parameters[254], gameLogDate); - this.photonUserLeave(data.Parameters[254], gameLogDate); - this.photonLobbyCurrent.delete(data.Parameters[254]); - this.photonLobbyJointime.delete(data.Parameters[254]); - this.photonLobbyInVrMode.delete(data.Parameters[254]); - this.photonEvent7List.delete(data.Parameters[254]); - this.parsePhotonLobbyIds(data.Parameters[252]); - if (typeof data.Parameters[203] !== 'undefined') { - this.setPhotonLobbyMaster(data.Parameters[203], gameLogDate); - } - } else if (data.Code === 4) { - // Sync - this.setPhotonLobbyMaster(data.Parameters[254], gameLogDate); - } else if (data.Code === 33) { - // Moderation - if (data.Parameters[245]['0'] === 21) { - if (data.Parameters[245]['1']) { - var photonId = data.Parameters[245]['1']; - var block = data.Parameters[245]['10']; - var mute = data.Parameters[245]['11']; - var ref = this.photonLobby.get(photonId); - if ( - typeof ref !== 'undefined' && - typeof ref.id !== 'undefined' - ) { - this.photonModerationUpdate( - ref, - photonId, - block, - mute, + switch (data.Code) { + case 253: + // SetUserProperties + if (data.Parameters[253] === -1) { + for (var i in data.Parameters[251]) { + var id = parseInt(i, 10); + var user = data.Parameters[251][i]; + this.parsePhotonUser(id, user.user, gameLogDate); + this.parsePhotonAvatarChange( + id, + user.user, + user.avatarDict, gameLogDate ); - } else { - this.moderationEventQueue.set(photonId, { - block, - mute, - gameLogDate + this.parsePhotonAvatar(user.avatarDict); + this.parsePhotonAvatar(user.favatarDict); + if (typeof user.inVRMode !== 'undefined') { + this.photonLobbyInVrMode.set(id, user.inVRMode); + } + this.photonLobbyJointime.set(id, { + joinTime: Date.parse(gameLogDate), + hasInstantiated: false, + inVRMode: user.inVRMode, + avatarEyeHeight: user.avatarEyeHeight }); } } else { - var blockArray = data.Parameters[245]['10']; - var muteArray = data.Parameters[245]['11']; - var 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) => { - var ref1 = this.photonLobby.get(photonId3); + this.parsePhotonUser( + data.Parameters[253], + data.Parameters[251].user, + gameLogDate + ); + this.parsePhotonAvatarChange( + data.Parameters[253], + data.Parameters[251].user, + data.Parameters[251].avatarDict, + gameLogDate + ); + this.parsePhotonAvatar(data.Parameters[251].avatarDict); + this.parsePhotonAvatar(data.Parameters[251].favatarDict); + if (typeof data.Parameters[251].inVRMode !== 'undefined') { + this.photonLobbyInVrMode.set( + data.Parameters[253], + data.Parameters[251].inVRMode + ); + } + } + break; + case 42: + // SetUserProperties + this.parsePhotonUser( + data.Parameters[254], + data.Parameters[245].user, + gameLogDate + ); + this.parsePhotonAvatarChange( + data.Parameters[254], + data.Parameters[245].user, + data.Parameters[245].avatarDict, + gameLogDate + ); + this.parsePhotonAvatar(data.Parameters[245].avatarDict); + this.parsePhotonAvatar(data.Parameters[245].favatarDict); + if (typeof data.Parameters[245].inVRMode !== 'undefined') { + this.photonLobbyInVrMode.set( + data.Parameters[254], + data.Parameters[245].inVRMode + ); + } + break; + case 255: + // Join + if (typeof data.Parameters[249] !== 'undefined') { + this.parsePhotonUser( + data.Parameters[254], + data.Parameters[249].user, + gameLogDate + ); + this.parsePhotonAvatarChange( + data.Parameters[254], + data.Parameters[249].user, + data.Parameters[249].avatarDict, + gameLogDate + ); + this.parsePhotonAvatar(data.Parameters[249].avatarDict); + this.parsePhotonAvatar(data.Parameters[249].favatarDict); + } + if (typeof data.Parameters[249].inVRMode !== 'undefined') { + this.photonLobbyInVrMode.set( + data.Parameters[254], + data.Parameters[249].inVRMode + ); + } + this.parsePhotonLobbyIds(data.Parameters[252]); + var hasInstantiated = false; + if (this.photonLobbyCurrentUser === data.Parameters[254]) { + hasInstantiated = true; + } + this.photonLobbyJointime.set(data.Parameters[254], { + joinTime: Date.parse(gameLogDate), + hasInstantiated, + inVRMode: data.Parameters[249].inVRMode, + avatarEyeHeight: data.Parameters[249].avatarEyeHeight + }); + var ref = this.photonLobbyCurrent.get(data.Parameters[254]); + this.photonUserJoin( + data.Parameters[254], + data.Parameters[249].avatarDict, + gameLogDate + ); + this.checkPhotonBotJoin( + data.Parameters[254], + data.Parameters[249], + gameLogDate + ); + this.startLobbyWatcherLoop(); + break; + case 254: + // Leave + this.checkPhotonBotLeave(data.Parameters[254], gameLogDate); + this.photonUserLeave(data.Parameters[254], gameLogDate); + this.photonLobbyCurrent.delete(data.Parameters[254]); + this.photonLobbyJointime.delete(data.Parameters[254]); + this.photonLobbyInVrMode.delete(data.Parameters[254]); + this.photonEvent7List.delete(data.Parameters[254]); + this.parsePhotonLobbyIds(data.Parameters[252]); + if (typeof data.Parameters[203] !== 'undefined') { + this.setPhotonLobbyMaster( + data.Parameters[203], + gameLogDate + ); + } + break; + case 4: + // Sync + this.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']; + var block = data.Parameters[245]['10']; + var mute = data.Parameters[245]['11']; + var ref = this.photonLobby.get(photonId); if ( - typeof ref1 !== 'undefined' && - typeof ref1.id !== 'undefined' + typeof ref !== 'undefined' && + typeof ref.id !== 'undefined' ) { this.photonModerationUpdate( - ref1, - photonId3, - isBlock, - isMute, + ref, + photonId, + block, + mute, gameLogDate ); } else { - this.moderationEventQueue.set(photonId3, { - block: isBlock, - mute: isMute, + this.moderationEventQueue.set(photonId, { + block, + mute, gameLogDate }); } + } else { + var blockArray = data.Parameters[245]['10']; + var muteArray = data.Parameters[245]['11']; + var 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) => { + var ref1 = this.photonLobby.get(photonId3); + if ( + typeof ref1 !== 'undefined' && + typeof ref1.id !== 'undefined' + ) { + this.photonModerationUpdate( + ref1, + photonId3, + isBlock, + isMute, + gameLogDate + ); + } else { + this.moderationEventQueue.set(photonId3, { + block: isBlock, + mute: isMute, + gameLogDate + }); + } + }); + } + } + break; + case 202: + // Instantiate + if (!this.photonLobby.has(data.Parameters[254])) { + this.photonLobby.set(data.Parameters[254]); + } + if (!this.photonLobbyCurrent.has(data.Parameters[254])) { + this.photonLobbyCurrent.set(data.Parameters[254]); + } + var lobbyJointime = this.photonLobbyJointime.get( + data.Parameters[254] + ); + if (typeof lobbyJointime !== 'undefined') { + this.photonLobbyJointime.set(data.Parameters[254], { + ...lobbyJointime, + hasInstantiated: true }); } - } - } else if (data.Code === 202) { - // Instantiate - if (!this.photonLobby.has(data.Parameters[254])) { - this.photonLobby.set(data.Parameters[254]); - } - if (!this.photonLobbyCurrent.has(data.Parameters[254])) { - this.photonLobbyCurrent.set(data.Parameters[254]); - } - var lobbyJointime = this.photonLobbyJointime.get( - data.Parameters[254] - ); - if (typeof lobbyJointime !== 'undefined') { - this.photonLobbyJointime.set(data.Parameters[254], { - ...lobbyJointime, - hasInstantiated: true + break; + case 43: + // Chatbox Message + var photonId = data.Parameters[254]; + var text = data.Parameters[245]; + this.addEntryPhotonEvent({ + photonId, + text, + type: 'ChatBoxMessage', + created_at: gameLogDate }); - } + var entry = { + userId: this.getUserIdFromPhotonId(photonId), + displayName: this.getDisplayNameFromPhotonId(photonId), + created_at: gameLogDate, + type: 'ChatBoxMessage', + text + }; + this.queueGameLogNoty(entry); + this.addGameLog(entry); + break; } }; @@ -9196,23 +9315,23 @@ speechSynthesis.getVoices(); var displayName = this.getDisplayNameFromPhotonId(senderId); API.getInstanceFromShortName({shortName}).then((args) => { var location = args.json.location; + var newShortName = args.json.shortName; var ref = { id: this.getUserIdFromPhotonId(senderId), displayName }; - this.parsePhotonPortalSpawn(datetime, location, ref); var portalType = 'Secure'; - if (shortName === args.json.shortName) { + if (shortName === newShortName) { portalType = 'Unlocked'; } - this.addEntryPhotonEvent({ - photonId: senderId, - text: `${portalType} PortalSpawn`, - type: 'PortalSpawn', - shortName, + this.parsePhotonPortalSpawn( + datetime, location, - created_at: datetime - }); + ref, + portalType, + newShortName, + senderId + ); return args; }); return; @@ -9276,7 +9395,10 @@ speechSynthesis.getVoices(); $app.methods.parsePhotonPortalSpawn = async function ( created_at, instanceId, - ref + ref, + portalType, + shortName, + photonId ) { var L = API.parseLocation(instanceId); var name = instanceId; @@ -9286,6 +9408,15 @@ speechSynthesis.getVoices(); }); name = args.ref.name; } catch (err) {} + this.addEntryPhotonEvent({ + photonId, + text: `${portalType} PortalSpawn to ${name}`, + type: 'PortalSpawn', + shortName, + location: instanceId, + worldName: name, + created_at + }); this.addPhotonEventToGameLog({ created_at, type: 'PortalSpawn', @@ -9526,7 +9657,7 @@ speechSynthesis.getVoices(); this.photonLobbyUserData.set(photonId, photonUser); }; - $app.methods.photonUserJoin = function (photonId, ref, gameLogDate) { + $app.methods.photonUserJoin = function (photonId, avatar, gameLogDate) { if ( photonId === this.photonLobbyCurrentUser || !this.photonEventOverlayJoinLeave @@ -9537,7 +9668,8 @@ speechSynthesis.getVoices(); photonId, text: 'has joined', type: 'OnPlayerJoined', - created_at: gameLogDate + created_at: gameLogDate, + avatar }); }; @@ -9677,9 +9809,13 @@ speechSynthesis.getVoices(); $app.methods.parsePhotonAvatar = function (avatar) { var tags = []; + var unityPackages = []; if (typeof avatar.tags !== 'undefined') { tags = avatar.tags; } + if (typeof avatar.unityPackages !== 'undefined') { + unityPackages = avatar.unityPackages; + } API.applyAvatar({ id: avatar.id, authorId: avatar.authorId, @@ -9692,7 +9828,8 @@ speechSynthesis.getVoices(); name: avatar.name, releaseStatus: avatar.releaseStatus, version: avatar.version, - tags + tags, + unityPackages }); }; @@ -11620,6 +11757,15 @@ speechSynthesis.getVoices(); configRepository.getString('VRCX_notificationTableFilters') ); } + if (configRepository.getString('VRCX_photonEventTypeFilter')) { + $app.data.photonEventTableTypeFilter = JSON.parse( + configRepository.getString('VRCX_photonEventTypeFilter') + ); + $app.data.photonEventTable.filters[1].value = + $app.data.photonEventTableTypeFilter; + $app.data.photonEventTablePrevious.filters[1].value = + $app.data.photonEventTableTypeFilter; + } // App: Profile + Settings @@ -11999,9 +12145,6 @@ speechSynthesis.getVoices(); 'VRCX_PhotonEventOverlayJoinLeave' ); $app.data.photonLoggingEnabled = false; - // $app.data.photonLoggingEnabled = configRepository.getBool( - // 'VRCX_photonLoggingEnabled' - // ); $app.data.gameLogDisabled = configRepository.getBool( 'VRCX_gameLogDisabled' ); @@ -12171,6 +12314,7 @@ speechSynthesis.getVoices(); MutedOnPlayerJoined: 'Off', MutedOnPlayerLeft: 'Off', AvatarChange: 'Off', + ChatBoxMessage: 'Off', Blocked: 'Off', Unblocked: 'Off', Muted: 'Off', @@ -12202,6 +12346,7 @@ speechSynthesis.getVoices(); MutedOnPlayerJoined: 'Off', MutedOnPlayerLeft: 'Off', AvatarChange: 'Everyone', + ChatBoxMessage: 'Off', Blocked: 'On', Unblocked: 'On', Muted: 'On', @@ -12662,13 +12807,11 @@ speechSynthesis.getVoices(); if (input.startsWith('/home/')) { input = `https://vrchat.com${input}`; } - if (input.startsWith('https://vrch.at/')) { + if (input.length === 8) { + return this.verifyShortName('', input); + } else if (input.startsWith('https://vrch.at/')) { var shortName = input.substring(16, 24); - return API.getInstanceFromShortName({shortName}).then((args) => { - var location = args.json.location; - this.directAccessWorld(location); - return args; - }); + return this.verifyShortName('', shortName); } else if ( input.startsWith('https://vrchat.') || input.startsWith('/home/') @@ -12686,8 +12829,7 @@ speechSynthesis.getVoices(); if (instanceId) { var shortName = urlParams.get('shortName'); var location = `${worldId}:${instanceId}`; - this.showWorldDialog(location, shortName); - return true; + return this.verifyShortName(location, shortName); } else if (worldId) { this.showWorldDialog(worldId); return true; @@ -12705,7 +12847,25 @@ speechSynthesis.getVoices(); return false; }; + $app.methods.verifyShortName = function (location, shortName) { + return API.getInstanceFromShortName({shortName}).then((args) => { + var newLocation = args.json.location; + var newShortName = args.json.shortName; + if (newShortName) { + this.showWorldDialog(newLocation, newShortName); + } else if (newLocation) { + this.showWorldDialog(newLocation); + } else { + this.showWorldDialog(location); + } + return args; + }); + }; + $app.methods.directAccessParse = function (input) { + if (!input) { + return false; + } var testUrl = input.substring(0, 15); if (this.directAccessWorld(input)) { return true; @@ -15537,7 +15697,8 @@ speechSynthesis.getVoices(); strict: false, location: '', shortName: '', - url: '' + url: '', + secureOrShortName: '' }; API.$on('LOGOUT', function () { @@ -15618,7 +15779,7 @@ speechSynthesis.getVoices(); }; $app.methods.updateNewInstanceDialog = function (noChanges) { - var D = $app.newInstanceDialog; + var D = this.newInstanceDialog; if (D.instanceId) { D.location = `${D.worldId}:${D.instanceId}`; } else { @@ -15864,7 +16025,8 @@ speechSynthesis.getVoices(); location: '', url: '', shortName: '', - shortUrl: '' + shortUrl: '', + secureOrShortName: '' }; $app.watch['launchDialog.desktop'] = function () { @@ -15880,23 +16042,24 @@ speechSynthesis.getVoices(); return; } var shortName = args.json.shortName; - var location = `${args.instance.worldId}:${args.instance.instanceId}`; - var L = this.parseLocation(location); + var secureOrShortName = shortName; if (!shortName) { - if (location === $app.launchDialog.tag && args.json.secureName) { - $app.launchDialog.location = `${L.worldId}:${L.instanceId}&shortName=${args.json.secureName}`; - } - return; + secureOrShortName = args.json.secureName; } + var location = `${args.instance.worldId}:${args.instance.instanceId}`; if (location === $app.launchDialog.tag) { + var L = this.parseLocation(location); L.shortName = shortName; $app.launchDialog.shortName = shortName; - $app.launchDialog.shortUrl = `https://vrch.at/${shortName}`; + $app.launchDialog.secureOrShortName = secureOrShortName; + if (shortName) { + $app.launchDialog.shortUrl = `https://vrch.at/${shortName}`; + } $app.launchDialog.url = $app.getLaunchURL(L); - $app.launchDialog.location = `${L.worldId}:${L.instanceId}&shortName=${shortName}`; } if (location === $app.newInstanceDialog.location) { $app.newInstanceDialog.shortName = shortName; + $app.newInstanceDialog.secureOrShortName = secureOrShortName; $app.updateNewInstanceDialog(true); } }); @@ -15916,27 +16079,25 @@ speechSynthesis.getVoices(); this.$nextTick(() => adjustDialogZ(this.$refs.launchDialog.$el)); var D = this.launchDialog; D.tag = tag; + D.secureOrShortName = shortName; D.shortUrl = ''; - D.shortName = ''; + D.shortName = shortName; var L = API.parseLocation(tag); L.shortName = shortName; if (L.isOffline || L.isPrivate || L.isTraveling || L.worldId === '') { return; } if (shortName) { - D.shortName = shortName; D.shortUrl = `https://vrch.at/${shortName}`; } - if (shortName && L.instanceId) { - D.location = `${L.worldId}:${L.instanceId}&shortName=${shortName}`; - } else if (L.instanceId) { + if (L.instanceId) { D.location = `${L.worldId}:${L.instanceId}`; } else { D.location = L.worldId; } D.url = this.getLaunchURL(L); D.visible = true; - if (L.userId && !shortName) { + if (!shortName) { API.getInstanceShortName({ worldId: L.worldId, instanceId: L.instanceId @@ -15963,12 +16124,14 @@ speechSynthesis.getVoices(); )}`; }; - $app.methods.locationToLaunchArg = function (location) { - return `vrchat://launch?id=${location}`; - }; - - $app.methods.launchGame = function (...args) { + $app.methods.launchGame = function (location, shortName) { var D = this.launchDialog; + var args = ''; + if (shortName) { + args = `vrchat://launch?id=${location}&shortName=${shortName}`; + } else { + args = `vrchat://launch?id=${location}`; + } var {launchArguments, vrcLaunchPathOverride} = this.launchOptionsDialog; if (launchArguments) { args.push(launchArguments); @@ -19522,6 +19685,7 @@ speechSynthesis.getVoices(); if (typeof data.Parameters[252] !== 'undefined') { this.parsePhotonLobbyIds(data.Parameters[252]); } + this.photonEvent7List = new Map(); break; } }; diff --git a/html/src/index.pug b/html/src/index.pug index c010d606..22d71cb7 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -186,7 +186,9 @@ html img(:src="getFaviconUrl(link)" style="width:16px;height:16px;vertical-align:middle;margin-right:5px;cursor:pointer" @click.stop="openExternalLink(link)") div.photon-event-table(v-if="photonLoggingEnabled") div(style="position:absolute;margin-left:195px;z-index:1") - el-input(v-model="photonEventTableFilter" @input="photonEventTableFilterChange" placeholder="Search" clearable style="width:150px") + el-select(v-model="photonEventTableTypeFilter" @change="photonEventTableFilterChange" multiple clearable collapse-tags style="flex:1" placeholder="Filter") + el-option(v-once v-for="type in ['AvatarChange', 'ChangeStatus', 'PortalSpawn', 'DeletedPortal', 'ChatBoxMessage', 'Event', 'PhotonMasterMigrate', 'PhotonBot', 'OnPlayerJoined', 'OnPlayerLeft', 'Moderation']" :key="type" :label="type" :value="type") + el-input(v-model="photonEventTableFilter" @input="photonEventTableFilterChange" placeholder="Search" clearable style="width:150px;margin-left:10px") el-tooltip(placement="bottom" content="VRCX Companion Status" :disabled="hideTooltips") div(style="display:inline-block;margin-left:15px;font-size:14px;vertical-align:text-top;margin-top:1px") span(v-if="ipcEnabled && !photonEventIcon") 🟢 @@ -206,7 +208,7 @@ html span.x-link(v-text="scope.row.displayName" @click="showUserFromPhotonId(scope.row.photonId)" style="padding-right:10px") el-table-column(label="Event" prop="text") template(v-once #default="scope") - span(v-if="scope.row.type === 'AvatarChange'") + template(v-if="scope.row.type === 'AvatarChange'") span ChangeAvatar span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)") |   @@ -236,8 +238,15 @@ html span(v-else) Offline i.x-user-status(:class="statusClass(scope.row.status)") span(v-if="scope.row.statusDescription !== scope.row.previousStatusDescription" v-text="scope.row.statusDescription" style="margin-left:10px") + span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" @click="showWorldDialog(scope.row.location, scope.row.shortName)") + | PortalSpawn #[location(:location="scope.row.location" :hint="scope.row.worldName" :link="false")] + span(v-else-if="scope.row.type === 'ChatBoxMessage'") + | ChatBox #[span(v-text="scope.row.text")] + span(v-else-if="scope.row.type === 'OnPlayerJoined'") + | has joined - #[span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")]  + span.avatar-info-public(v-if="scope.row.avatar.releaseStatus === 'public'") (Public) + span.avatar-info-own(v-else-if="scope.row.avatar.releaseStatus === 'private'") (Private) span(v-else-if="scope.row.color === 'yellow'" v-text="scope.row.text" style="color:yellow") - span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" v-text="scope.row.text" @click="showWorldDialog(scope.row.location, scope.row.shortName)") span(v-else v-text="scope.row.text") el-tab-pane(label="Previous") data-tables(v-bind="photonEventTablePrevious" style="margin-bottom:10px") @@ -282,6 +291,14 @@ html span(v-else) Offline i.x-user-status(:class="statusClass(scope.row.status)") span(v-if="scope.row.statusDescription !== scope.row.previousStatusDescription" v-text="scope.row.statusDescription" style="margin-left:10px") + span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" @click="showWorldDialog(scope.row.location, scope.row.shortName)") + | PortalSpawn #[location(:location="scope.row.location" :hint="scope.row.worldName" :link="false")] + span(v-else-if="scope.row.type === 'ChatBoxMessage'") + | ChatBox #[span(v-text="scope.row.text")] + span(v-else-if="scope.row.type === 'OnPlayerJoined'") + | has joined - #[span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")]  + span.avatar-info-public(v-if="scope.row.avatar.releaseStatus === 'public'") (Public) + span.avatar-info-own(v-else-if="scope.row.avatar.releaseStatus === 'private'") (Private) span(v-else-if="scope.row.color === 'yellow'" v-text="scope.row.text" style="color:yellow") span(v-else v-text="scope.row.text") @@ -1121,6 +1138,9 @@ html el-tab-pane(label="Notifications") div.options-container(style="margin-top:0") span.header Notifications + div.options-container-item + el-button(size="small" icon="el-icon-chat-square" @click="showNotyFeedFiltersDialog") Notification Filters + span.sub-header SteamVR Notifications div.options-container-item span.name SteamVR Overlay el-switch(v-model="openVR" @change="saveOpenVROption") @@ -1149,8 +1169,6 @@ html el-radio-button(label="Game Closed") el-radio-button(label="Game Running") el-radio-button(label="Always") - div.options-container-item - el-button(size="small" icon="el-icon-chat-square" @click="showNotyFeedFiltersDialog") Notification Filters br span.sub-header Text-To-Speech Options div.options-container-item @@ -1810,6 +1828,7 @@ html div(v-for="room in worldDialog.rooms" :key="room.id") div(style="margin:5px 0") span.x-link(@click="showLaunchDialog(room.$location.tag, room.$location.shortName)") + i.el-icon-unlock(v-if="(room.$location.shortName && worldDialog.$location.shortName === room.$location.shortName) || API.currentUser.id === room.$location.userId" style="display:inline-block;margin-right:5px") span \#{{ room.$location.instanceName }} {{ room.$location.accessType }} span.flags(v-if="room.$location.region" :class="room.$location.region" style="display:inline-block;margin-left:5px") span.flags(v-else class="us" style="display:inline-block;margin-left:5px") @@ -2174,7 +2193,7 @@ html el-button(size="small" @click="copyInstanceUrl(newInstanceDialog.location)") Copy URL el-button(size="small" @click="selfInvite(newInstanceDialog.location)") Self Invite el-button(size="small" @click="showInviteDialog(newInstanceDialog.location)" :disabled="(newInstanceDialog.accessType === 'friends' || newInstanceDialog.accessType === 'invite') && newInstanceDialog.userId !== API.currentUser.id") Invite - el-button(type="primary" size="small" @click="showLaunchDialog(newInstanceDialog.location)") Launch + el-button(type="primary" size="small" @click="showLaunchDialog(newInstanceDialog.location, newInstanceDialog.secureOrShortName)") Launch //- dialog: launch options el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="launchOptionsDialog" :visible.sync="launchOptionsDialog.visible" title="Launch Options" width="500px") @@ -2325,7 +2344,7 @@ html el-checkbox(v-model="launchDialog.desktop" style="float:left;margin-top:5px") Start as Desktop (No VR) el-button(size="small" @click="showPreviousInstanceInfoDialog(launchDialog.location)") Info el-button(size="small" @click="showInviteDialog(launchDialog.location)" :disabled="!checkCanInvite(launchDialog.location)") Invite - el-button(type="primary" size="small" @click="launchGame(locationToLaunchArg(launchDialog.location))") Launch + el-button(type="primary" size="small" @click="launchGame(launchDialog.location, launchDialog.secureOrShortName)" :disabled="!launchDialog.secureOrShortName") Launch //- dialog: export friends list el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="exportFriendsListDialog" title="Export Friends List" width="650px") @@ -2520,6 +2539,13 @@ html el-radio-button(label="VIP") el-radio-button(label="Friends") el-radio-button(label="Everyone") + .toggle-item + span.toggle-name Lobby ChatBox Message + el-radio-group(v-model="sharedFeedFilters.noty.ChatBoxMessage" size="mini") + el-radio-button(label="Off") + el-radio-button(label="VIP") + el-radio-button(label="Friends") + el-radio-button(label="Everyone") .toggle-item span.toggle-name Blocked el-radio-group(v-model="sharedFeedFilters.noty.Blocked" size="mini") @@ -2707,6 +2733,13 @@ html el-radio-button(label="VIP") el-radio-button(label="Friends") el-radio-button(label="Everyone") + .toggle-item + span.toggle-name Lobby ChatBox Message + el-radio-group(v-model="sharedFeedFilters.wrist.ChatBoxMessage" size="mini") + el-radio-button(label="Off") + el-radio-button(label="VIP") + el-radio-button(label="Friends") + el-radio-button(label="Everyone") .toggle-item span.toggle-name Blocked el-radio-group(v-model="sharedFeedFilters.wrist.Blocked" size="mini") diff --git a/html/src/vr.js b/html/src/vr.js index 8c348c7d..b9c72b50 100644 --- a/html/src/vr.js +++ b/html/src/vr.js @@ -449,11 +449,23 @@ Vue.component('marquee-text', MarqueeText); text = `${noty.previousDisplayName} changed their name to ${noty.displayName}`; break; case 'PortalSpawn': - text = 'User has spawned a portal'; + if (noty.displayName) { + text = `${ + noty.displayName + } has spawned a portal to ${this.displayLocation( + noty.instanceId, + noty.worldName + )}`; + } else { + text = 'User has spawned a portal'; + } break; case 'AvatarChange': text = `${noty.displayName} changed into avatar ${noty.name}`; break; + case 'ChatBoxMessage': + text = `${noty.displayName} said ${noty.text}`; + break; case 'Event': text = noty.data; break; diff --git a/html/src/vr.pug b/html/src/vr.pug index 7109e1c6..56323cb7 100644 --- a/html/src/vr.pug +++ b/html/src/vr.pug @@ -123,7 +123,11 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | ✨ User has spawned a portal + template(v-if="feed.displayName") + | ✨ #[span.name(v-text="feed.displayName")] + | #[location(:location="feed.instanceId" :hint="feed.worldName")] + template(v-else) + | ✨ User has spawned a portal div(v-else-if="feed.type === 'AvatarChange'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra @@ -136,6 +140,11 @@ html | {{ feed.name }} template(v-if="feed.description && feed.description !== feed.name") | - {{ feed.description }} + div(v-else-if="feed.type === 'ChatBoxMessage'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") + .detail + span.extra + span.time {{ feed.created_at | formatDate }} + | 💬 #[span.name(v-text="feed.displayName")] #[span(v-text="feed.text")] div(v-else-if="feed.type === 'Event'" class="x-friend-item") .detail span.extra @@ -292,7 +301,11 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | User has spawned a portal + template(v-if="feed.displayName") + | #[span.name(v-text="feed.displayName")] has spawned a portal to + | #[location(:location="feed.instanceId" :hint="feed.worldName")] + template(v-else) + | User has spawned a portal div(v-else-if="feed.type === 'AvatarChange'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra @@ -305,6 +318,11 @@ html | {{ feed.name }} template(v-if="feed.description && feed.description !== feed.name") | - {{ feed.description }} + div(v-else-if="feed.type === 'ChatBoxMessage'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") + .detail + span.extra + span.time {{ feed.created_at | formatDate }} + | #[span.name(v-text="feed.displayName")] said #[span(v-text="feed.text")] div(v-else-if="feed.type === 'Event'" class="x-friend-item") .detail span.extra @@ -424,7 +442,7 @@ html .hud-feed div(v-for="feed in hudFeed") .item #[span(v-if="feed.isMaster") 👑]{{ feed.displayName }} - span(v-if="feed.type === 'AvatarChange'") + template(v-if="feed.type === 'AvatarChange'") span(style="margin-left:10px") ChangeAvatar span(v-if="!feed.inCache" style="color:#aaa;margin-left:10px") #[i.el-icon-download] span(v-text="feed.avatar.name" style="margin-left:10px") @@ -438,6 +456,17 @@ html i.el-icon-right i.x-user-status(:class="statusClass(feed.status)" style="width:20px;height:20px") span(v-if="feed.statusDescription !== feed.previousStatusDescription" v-text="feed.statusDescription" style="margin-left:10px") + template(v-else-if="feed.type === 'ChatBoxMessage'") + span(style="margin-left:10px") ChatBox + span(v-text="feed.text" style="margin-left:10px;white-space:normal") + template(v-else-if="feed.type === 'PortalSpawn'") + span(style="margin-left:10px") PortalSpawn + location(:location="feed.location" :hint="feed.worldName" :link="false" style="margin-left:10px") + template(v-else-if="feed.type === 'OnPlayerJoined'") + span(style="margin-left:10px") has joined - + span(v-text="feed.avatar.name" style="margin-left:10px") + span(v-if="feed.avatar.releaseStatus === 'public'" style="margin-left:10px;color:#67c23a") (Public) + span(v-else-if="feed.avatar.releaseStatus === 'private'" style="margin-left:10px;color:#e6a23c") (Private) span(v-else-if="feed.color === 'yellow'" v-text="feed.text" style="color:yellow;margin-left:10px") span(v-else style="margin-left:10px" v-text="feed.text") template(v-if="feed.combo > 1")