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")