From 7e84ac5454526782643e13cc8bce3925f2aa5dd7 Mon Sep 17 00:00:00 2001 From: Piotr Hanusiak Date: Mon, 4 Apr 2022 13:47:23 +0200 Subject: [PATCH] Global voice-indicators (#2020) * make use of well known types for PlayerDetailsUpdated message * show voice-chat indicator of people from other groups too * cleanup * check for outline value * do not send outline color if undefined * revert removing LocalVolumeStore * use auto-generated type instead Co-authored-by: Piotr 'pwh' Hanusiak --- back/src/Model/GameRoom.ts | 6 +-- back/src/Model/User.ts | 27 +++++++--- back/src/Services/SocketManager.ts | 5 +- front/src/Connexion/ConnexionModels.ts | 6 --- front/src/Connexion/RoomConnection.ts | 14 +++++ front/src/Phaser/Game/GameScene.ts | 71 +++++++++++--------------- messages/protos/messages.proto | 9 ++-- pusher/src/Model/Zone.ts | 2 +- 8 files changed, 71 insertions(+), 69 deletions(-) diff --git a/back/src/Model/GameRoom.ts b/back/src/Model/GameRoom.ts index 157faa4e..72161d86 100644 --- a/back/src/Model/GameRoom.ts +++ b/back/src/Model/GameRoom.ts @@ -210,11 +210,7 @@ export class GameRoom { } updatePlayerDetails(user: User, playerDetailsMessage: SetPlayerDetailsMessage) { - if (playerDetailsMessage.getRemoveoutlinecolor()) { - user.outlineColor = undefined; - } else { - user.outlineColor = playerDetailsMessage.getOutlinecolor(); - } + user.updateDetails(playerDetailsMessage); } private updateUserGroup(user: User): void { diff --git a/back/src/Model/User.ts b/back/src/Model/User.ts index c6abf52a..516a6b08 100644 --- a/back/src/Model/User.ts +++ b/back/src/Model/User.ts @@ -15,6 +15,7 @@ import { SubMessage, } from "../Messages/generated/messages_pb"; import { CharacterLayer } from "_Model/Websocket/CharacterLayer"; +import { BoolValue, UInt32Value } from "google-protobuf/google/protobuf/wrappers_pb"; export type UserSocket = ServerDuplexStream; @@ -37,7 +38,8 @@ export class User implements Movable { public readonly name: string, public readonly characterLayers: CharacterLayer[], public readonly companion?: CompanionMessage, - private _outlineColor?: number | undefined + private outlineColor?: number, + private voiceIndicatorShown?: boolean ) { this.listenedZones = new Set(); @@ -83,6 +85,10 @@ export class User implements Movable { return this.followedBy.size !== 0; } + public getOutlineColor(): number | undefined { + return this.outlineColor; + } + get following(): User | undefined { return this._following; } @@ -115,14 +121,21 @@ export class User implements Movable { } } - public set outlineColor(value: number | undefined) { - this._outlineColor = value; + public updateDetails(details: SetPlayerDetailsMessage) { + if (details.getRemoveoutlinecolor()) { + this.outlineColor = undefined; + } else if (details.getOutlinecolor()?.getValue() !== undefined) { + this.outlineColor = details.getOutlinecolor()?.getValue(); + } + this.voiceIndicatorShown = details.getShowvoiceindicator()?.getValue(); const playerDetails = new SetPlayerDetailsMessage(); - if (value === undefined) { - playerDetails.setRemoveoutlinecolor(true); - } else { - playerDetails.setOutlinecolor(value); + + if (this.outlineColor !== undefined) { + playerDetails.setOutlinecolor(new UInt32Value().setValue(this.outlineColor)); + } + if (this.voiceIndicatorShown !== undefined) { + playerDetails.setShowvoiceindicator(new BoolValue().setValue(this.voiceIndicatorShown)); } this.positionNotifier.updatePlayerDetails(this, playerDetails); diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index 8aa7f6a4..b9dfacd4 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -338,11 +338,12 @@ export class SocketManager { userJoinedZoneMessage.setVisitcardurl(thing.visitCardUrl); } userJoinedZoneMessage.setCompanion(thing.companion); - if (thing.outlineColor === undefined) { + const outlineColor = thing.getOutlineColor(); + if (outlineColor === undefined) { userJoinedZoneMessage.setHasoutline(false); } else { userJoinedZoneMessage.setHasoutline(true); - userJoinedZoneMessage.setOutlinecolor(thing.outlineColor); + userJoinedZoneMessage.setOutlinecolor(outlineColor); } const subMessage = new SubToPusherMessage(); diff --git a/front/src/Connexion/ConnexionModels.ts b/front/src/Connexion/ConnexionModels.ts index 84ce60c1..1c49b210 100644 --- a/front/src/Connexion/ConnexionModels.ts +++ b/front/src/Connexion/ConnexionModels.ts @@ -77,12 +77,6 @@ export interface ItemEventMessageInterface { parameters: unknown; } -export interface PlayerDetailsUpdatedMessageInterface { - userId: number; - outlineColor: number; - removeOutlineColor: boolean; -} - export interface RoomJoinedMessageInterface { //users: MessageUserPositionInterface[], //groups: GroupCreatedUpdatedMessageInterface[], diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 5cfc85c1..912e7bbc 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -504,6 +504,20 @@ export class RoomConnection implements RoomConnection { this.socket.send(clientToServerMessage.serializeBinary().buffer); }*/ + public emitPlayerShowVoiceIndicator(show: boolean): void { + const message = SetPlayerDetailsMessageTsProto.fromPartial({ + showVoiceIndicator: show, + }); + const bytes = ClientToServerMessageTsProto.encode({ + message: { + $case: "setPlayerDetailsMessage", + setPlayerDetailsMessage: message, + }, + }).finish(); + + this.socket.send(bytes); + } + public emitPlayerOutlineColor(color: number | null) { let message: SetPlayerDetailsMessageTsProto; if (color === null) { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 66a2d8eb..457702da 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -54,7 +54,6 @@ import type { MessageUserMovedInterface, MessageUserPositionInterface, OnConnectInterface, - PlayerDetailsUpdatedMessageInterface, PointInterface, PositionInterface, RoomJoinedMessageInterface, @@ -102,6 +101,7 @@ import type { VideoPeer } from "../../WebRtc/VideoPeer"; import CancelablePromise from "cancelable-promise"; import { Deferred } from "ts-deferred"; import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin"; +import { PlayerDetailsUpdatedMessage } from "../../Messages/ts-proto-generated/protos/messages"; export interface GameSceneInitInterface { initPosition: PointInterface | null; reconnecting: boolean; @@ -139,7 +139,7 @@ interface DeleteGroupEventInterface { interface PlayerDetailsUpdatedInterface { type: "PlayerDetailsUpdated"; - details: PlayerDetailsUpdatedMessageInterface; + details: PlayerDetailsUpdatedMessage; } export class GameScene extends DirtyScene { @@ -175,7 +175,6 @@ export class GameScene extends DirtyScene { private emoteUnsubscribe!: Unsubscriber; private emoteMenuUnsubscribe!: Unsubscriber; - private volumeStoreUnsubscribers: Map = new Map(); private localVolumeStoreUnsubscriber: Unsubscriber | undefined; private followUsersColorStoreUnsubscribe!: Unsubscriber; private currentPlayerGroupIdStoreUnsubscribe!: Unsubscriber; @@ -220,6 +219,7 @@ export class GameScene extends DirtyScene { private loader: Loader; private lastCameraEvent: WasCameraUpdatedEvent | undefined; private firstCameraUpdateSent: boolean = false; + private showVoiceIndicatorChangeMessageSent: boolean = false; private currentPlayerGroupId?: number; public readonly superLoad: SuperLoaderPlugin; @@ -634,55 +634,43 @@ export class GameScene extends DirtyScene { } const talkIconVolumeTreshold = 10; - const oldPeers = new Map(); + let oldPeersNumber = 0; this.peerStoreUnsubscribe = peerStore.subscribe((peers) => { - this.volumeStoreUnsubscribers.forEach((unsubscribe) => unsubscribe()); - this.volumeStoreUnsubscribers.clear(); - - for (const [key, videoStream] of peers) { - this.volumeStoreUnsubscribers.set( - key, - videoStream.volumeStore.subscribe((volume) => { - if (volume) { - this.MapPlayersByKey.get(key)?.showTalkIcon(volume > talkIconVolumeTreshold); - } - }) - ); - } - const newPeerNumber = peers.size; - if (newPeerNumber > oldPeers.size) { + if (newPeerNumber > oldPeersNumber) { this.playSound("audio-webrtc-in"); - } else if (newPeerNumber < oldPeers.size) { + } else if (newPeerNumber < oldPeersNumber) { this.playSound("audio-webrtc-out"); - const oldPeersKeys = oldPeers.keys(); - const newPeersKeys = Array.from(peers.keys()); - for (const oldKey of oldPeersKeys) { - if (!newPeersKeys.includes(oldKey)) { - this.MapPlayersByKey.get(oldKey)?.showTalkIcon(false, true); - } - } } if (newPeerNumber > 0) { if (!this.localVolumeStoreUnsubscriber) { this.localVolumeStoreUnsubscriber = localVolumeStore.subscribe((volume) => { - if (volume) { - this.CurrentPlayer.showTalkIcon(volume > talkIconVolumeTreshold); + if (volume === undefined) { + return; + } + const aboveTreshold = volume > talkIconVolumeTreshold; + this.CurrentPlayer.showTalkIcon(aboveTreshold); + + if (this.showVoiceIndicatorChangeMessageSent && !aboveTreshold) { + this.connection?.emitPlayerShowVoiceIndicator(false); + this.showVoiceIndicatorChangeMessageSent = false; + } else if (!this.showVoiceIndicatorChangeMessageSent && aboveTreshold) { + this.connection?.emitPlayerShowVoiceIndicator(true); + this.showVoiceIndicatorChangeMessageSent = true; } }); } } else { this.CurrentPlayer.showTalkIcon(false, true); + this.connection?.emitPlayerShowVoiceIndicator(false); + this.showVoiceIndicatorChangeMessageSent = false; this.MapPlayersByKey.forEach((remotePlayer) => remotePlayer.showTalkIcon(false, true)); if (this.localVolumeStoreUnsubscriber) { this.localVolumeStoreUnsubscriber(); this.localVolumeStoreUnsubscriber = undefined; } } - oldPeers.clear(); - for (const [key, val] of peers) { - oldPeers.set(key, val); - } + oldPeersNumber = peers.size; }); this.emoteUnsubscribe = emoteStore.subscribe((emote) => { @@ -834,11 +822,7 @@ export class GameScene extends DirtyScene { } this.pendingEvents.enqueue({ type: "PlayerDetailsUpdated", - details: { - userId: message.userId, - outlineColor: message.details.outlineColor, - removeOutlineColor: message.details.removeOutlineColor, - }, + details: message, }); }); @@ -2070,7 +2054,7 @@ ${escapedMessage} this.groups.delete(groupId); } - doUpdatePlayerDetails(message: PlayerDetailsUpdatedMessageInterface): void { + doUpdatePlayerDetails(message: PlayerDetailsUpdatedMessage): void { const character = this.MapPlayersByKey.get(message.userId); if (character === undefined) { console.log( @@ -2080,10 +2064,13 @@ ${escapedMessage} ); return; } - if (message.removeOutlineColor) { + if (message.details?.removeOutlineColor) { character.removeApiOutlineColor(); - } else { - character.setApiOutlineColor(message.outlineColor); + } else if (message.details?.outlineColor !== undefined) { + character.setApiOutlineColor(message.details?.outlineColor); + } + if (message.details?.showVoiceIndicator !== undefined) { + character.showTalkIcon(message.details?.showVoiceIndicator); } } diff --git a/messages/protos/messages.proto b/messages/protos/messages.proto index 35db5321..637d4aa1 100644 --- a/messages/protos/messages.proto +++ b/messages/protos/messages.proto @@ -50,12 +50,9 @@ message PingMessage { } message SetPlayerDetailsMessage { - //string name = 1; - //repeated string characterLayers = 2; - - // TODO: switch to google.protobuf.Int32Value when we migrate to ts-proto - uint32 outlineColor = 3; - bool removeOutlineColor = 4; + google.protobuf.UInt32Value outlineColor = 3; + google.protobuf.BoolValue removeOutlineColor = 4; + google.protobuf.BoolValue showVoiceIndicator = 5; } message UserMovesMessage { diff --git a/pusher/src/Model/Zone.ts b/pusher/src/Model/Zone.ts index f3b15ed2..3cc535a7 100644 --- a/pusher/src/Model/Zone.ts +++ b/pusher/src/Model/Zone.ts @@ -87,7 +87,7 @@ export class UserDescriptor { if (playerDetails.getRemoveoutlinecolor()) { this.outlineColor = undefined; } else { - this.outlineColor = playerDetails.getOutlinecolor(); + this.outlineColor = playerDetails.getOutlinecolor()?.getValue(); } }