Merge pull request #2091 from thecodingmachine/add-away-indicator-for-hero
Availability Statuses
This commit is contained in:
@@ -1,36 +1,41 @@
|
||||
import { AvailabilityStatus } from "../../Messages/ts-proto-generated/protos/messages";
|
||||
import { Easing } from "../../types";
|
||||
|
||||
export class PlayerStatusDot extends Phaser.GameObjects.Container {
|
||||
private graphics: Phaser.GameObjects.Graphics;
|
||||
private statusImage: Phaser.GameObjects.Image;
|
||||
private statusImageOutline: Phaser.GameObjects.Image;
|
||||
|
||||
private away: boolean;
|
||||
private status: AvailabilityStatus;
|
||||
|
||||
private readonly COLORS = {
|
||||
// online: 0x00ff00,
|
||||
// away: 0xffff00,
|
||||
online: 0x8cc43f,
|
||||
onlineOutline: 0x427a25,
|
||||
away: 0xf5931e,
|
||||
awayOutline: 0x875d13,
|
||||
private readonly COLORS: Record<AvailabilityStatus, { filling: number; outline: number }> = {
|
||||
[AvailabilityStatus.AWAY]: { filling: 0xf5931e, outline: 0x875d13 },
|
||||
[AvailabilityStatus.ONLINE]: { filling: 0x8cc43f, outline: 0x427a25 },
|
||||
[AvailabilityStatus.SILENT]: { filling: 0xe74c3c, outline: 0xc0392b },
|
||||
[AvailabilityStatus.JITSI]: { filling: 0x8cc43f, outline: 0x427a25 },
|
||||
[AvailabilityStatus.UNRECOGNIZED]: { filling: 0xffffff, outline: 0xffffff },
|
||||
[AvailabilityStatus.UNCHANGED]: { filling: 0xffffff, outline: 0xffffff },
|
||||
};
|
||||
|
||||
constructor(scene: Phaser.Scene, x: number, y: number) {
|
||||
super(scene, x, y);
|
||||
|
||||
this.away = false;
|
||||
this.status = AvailabilityStatus.ONLINE;
|
||||
|
||||
this.statusImage = this.scene.add.image(0, 0, "iconStatusIndicatorInside");
|
||||
this.statusImageOutline = this.scene.add.image(0, 0, "iconStatusIndicatorOutline");
|
||||
|
||||
this.add([this.statusImage, this.statusImageOutline]);
|
||||
|
||||
this.graphics = this.scene.add.graphics();
|
||||
this.add(this.graphics);
|
||||
this.redraw();
|
||||
|
||||
this.scene.add.existing(this);
|
||||
}
|
||||
|
||||
public setAway(away: boolean = true, instant: boolean = false): void {
|
||||
if (this.away === away) {
|
||||
public setStatus(status: AvailabilityStatus, instant: boolean = false): void {
|
||||
if (this.status === status || status === AvailabilityStatus.UNCHANGED) {
|
||||
return;
|
||||
}
|
||||
this.away = away;
|
||||
this.status = status;
|
||||
if (instant) {
|
||||
this.redraw();
|
||||
} else {
|
||||
@@ -56,10 +61,8 @@ export class PlayerStatusDot extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
private redraw(): void {
|
||||
this.graphics.clear();
|
||||
this.graphics.fillStyle(this.away ? this.COLORS.away : this.COLORS.online);
|
||||
this.graphics.lineStyle(1, this.away ? this.COLORS.awayOutline : this.COLORS.onlineOutline);
|
||||
this.graphics.fillCircle(0, 0, 3);
|
||||
this.graphics.strokeCircle(0, 0, 3);
|
||||
const colors = this.COLORS[this.status];
|
||||
this.statusImage.setTintFill(colors.filling);
|
||||
this.statusImageOutline.setTintFill(colors.outline);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { Companion } from "../Companion/Companion";
|
||||
import type { GameScene } from "../Game/GameScene";
|
||||
import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
|
||||
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
||||
import { isSilentStore } from "../../Stores/MediaStore";
|
||||
import { lazyLoadPlayerCharacterTextures } from "./PlayerTexturesLoadingManager";
|
||||
import { TexturesHelper } from "../Helpers/TexturesHelper";
|
||||
import type { PictureStore } from "../../Stores/PictureStore";
|
||||
@@ -20,6 +19,7 @@ import type CancelablePromise from "cancelable-promise";
|
||||
import { TalkIcon } from "../Components/TalkIcon";
|
||||
import { Deferred } from "ts-deferred";
|
||||
import { PlayerStatusDot } from "../Components/PlayerStatusDot";
|
||||
import { AvailabilityStatus } from "../../Messages/ts-proto-generated/protos/messages";
|
||||
|
||||
const playerNameY = -25;
|
||||
const interactiveRadius = 35;
|
||||
@@ -236,8 +236,8 @@ export abstract class Character extends Container implements OutlineableInterfac
|
||||
this.talkIcon.show(show, forceClose);
|
||||
}
|
||||
|
||||
public setAwayStatus(away: boolean = true, instant: boolean = false): void {
|
||||
this.statusDot.setAway(away, instant);
|
||||
public setStatus(status: AvailabilityStatus, instant: boolean = false): void {
|
||||
this.statusDot.setStatus(status, instant);
|
||||
}
|
||||
|
||||
public addCompanion(name: string, texturePromise?: CancelablePromise<string>): void {
|
||||
@@ -355,13 +355,6 @@ export abstract class Character extends Container implements OutlineableInterfac
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
isSilent() {
|
||||
isSilentStore.set(true);
|
||||
}
|
||||
noSilent() {
|
||||
isSilentStore.set(false);
|
||||
}
|
||||
|
||||
playEmote(emote: string) {
|
||||
this.cancelPreviousEmote();
|
||||
const emoteY = -45;
|
||||
|
||||
@@ -17,6 +17,7 @@ import { audioManagerFileStore, audioManagerVisibilityStore } from "../../Stores
|
||||
import { iframeListener } from "../../Api/IframeListener";
|
||||
import { Room } from "../../Connexion/Room";
|
||||
import LL from "../../i18n/i18n-svelte";
|
||||
import { inJitsiStore, silentStore } from "../../Stores/MediaStore";
|
||||
|
||||
interface OpenCoWebsite {
|
||||
actionId: string;
|
||||
@@ -77,6 +78,7 @@ export class GameMapPropertiesListener {
|
||||
coWebsiteManager.closeCoWebsite(coWebsite);
|
||||
}
|
||||
});
|
||||
inJitsiStore.set(false);
|
||||
} else {
|
||||
const openJitsiRoomFunction = () => {
|
||||
let addPrefix = true;
|
||||
@@ -119,11 +121,15 @@ export class GameMapPropertiesListener {
|
||||
uuid: "jitsi",
|
||||
type: "message",
|
||||
message: message,
|
||||
callback: () => openJitsiRoomFunction(),
|
||||
callback: () => {
|
||||
openJitsiRoomFunction();
|
||||
inJitsiStore.set(true);
|
||||
},
|
||||
userInputManager: this.scene.userInputManager,
|
||||
});
|
||||
} else {
|
||||
openJitsiRoomFunction();
|
||||
inJitsiStore.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -160,11 +166,9 @@ export class GameMapPropertiesListener {
|
||||
|
||||
this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue) => {
|
||||
if (newValue === undefined || newValue === false || newValue === "") {
|
||||
this.scene.connection?.setSilent(false);
|
||||
this.scene.CurrentPlayer.noSilent();
|
||||
silentStore.set(false);
|
||||
} else {
|
||||
this.scene.connection?.setSilent(true);
|
||||
this.scene.CurrentPlayer.isSilent();
|
||||
silentStore.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ import { MapStore } from "../../Stores/Utils/MapStore";
|
||||
import { followUsersColorStore } from "../../Stores/FollowStore";
|
||||
import { GameSceneUserInputHandler } from "../UserInput/GameSceneUserInputHandler";
|
||||
import { locale } from "../../i18n/i18n-svelte";
|
||||
import { localVolumeStore } from "../../Stores/MediaStore";
|
||||
import { availabilityStatusStore, localVolumeStore } from "../../Stores/MediaStore";
|
||||
import { StringUtils } from "../../Utils/StringUtils";
|
||||
import { startLayerNamesStore } from "../../Stores/StartLayerNamesStore";
|
||||
import { JitsiCoWebsite } from "../../WebRtc/CoWebsite/JitsiCoWebsite";
|
||||
@@ -101,7 +101,6 @@ import CancelablePromise from "cancelable-promise";
|
||||
import { Deferred } from "ts-deferred";
|
||||
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
|
||||
import { PlayerDetailsUpdatedMessage } from "../../Messages/ts-proto-generated/protos/messages";
|
||||
import { privacyShutdownStore } from "../../Stores/PrivacyShutdownStore";
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface | null;
|
||||
reconnecting: boolean;
|
||||
@@ -249,6 +248,8 @@ export class GameScene extends DirtyScene {
|
||||
this.listenToIframeEvents();
|
||||
|
||||
this.load.image("iconTalk", "/resources/icons/icon_talking.png");
|
||||
this.load.image("iconStatusIndicatorInside", "/resources/icons/icon_status_indicator_inside.png");
|
||||
this.load.image("iconStatusIndicatorOutline", "/resources/icons/icon_status_indicator_outline.png");
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
this.load.image(joystickBaseKey, joystickBaseImg);
|
||||
@@ -679,6 +680,11 @@ export class GameScene extends DirtyScene {
|
||||
this.tryChangeShowVoiceIndicatorState(this.jitsiDominantSpeaker && this.jitsiParticipantsCount > 1);
|
||||
});
|
||||
|
||||
availabilityStatusStore.subscribe((status) => {
|
||||
this.connection?.emitPlayerStatusChange(status);
|
||||
this.CurrentPlayer.setStatus(status);
|
||||
});
|
||||
|
||||
this.emoteUnsubscribe = emoteStore.subscribe((emote) => {
|
||||
if (emote) {
|
||||
this.CurrentPlayer?.playEmote(emote.url);
|
||||
@@ -705,10 +711,6 @@ export class GameScene extends DirtyScene {
|
||||
}
|
||||
});
|
||||
|
||||
this.privacyShutdownStoreUnsubscribe = privacyShutdownStore.subscribe((away) => {
|
||||
this.connection?.emitPlayerAway(away);
|
||||
});
|
||||
|
||||
Promise.all([
|
||||
this.connectionAnswerPromiseDeferred.promise as Promise<unknown>,
|
||||
...scriptPromises,
|
||||
@@ -767,7 +769,7 @@ export class GameScene extends DirtyScene {
|
||||
characterLayers: message.characterLayers,
|
||||
name: message.name,
|
||||
position: message.position,
|
||||
away: message.away,
|
||||
status: message.status,
|
||||
visitCardUrl: message.visitCardUrl,
|
||||
companion: message.companion,
|
||||
userUuid: message.userUuid,
|
||||
@@ -1933,8 +1935,8 @@ ${escapedMessage}
|
||||
if (addPlayerData.outlineColor !== undefined) {
|
||||
player.setApiOutlineColor(addPlayerData.outlineColor);
|
||||
}
|
||||
if (addPlayerData.away !== undefined) {
|
||||
player.setAwayStatus(addPlayerData.away, true);
|
||||
if (addPlayerData.status !== undefined) {
|
||||
player.setStatus(addPlayerData.status, true);
|
||||
}
|
||||
this.MapPlayers.add(player);
|
||||
this.MapPlayersByKey.set(player.userId, player);
|
||||
@@ -2085,8 +2087,8 @@ ${escapedMessage}
|
||||
if (message.details?.showVoiceIndicator !== undefined) {
|
||||
character.showTalkIcon(message.details?.showVoiceIndicator);
|
||||
}
|
||||
if (message.details?.away !== undefined) {
|
||||
character.setAwayStatus(message.details?.away);
|
||||
if (message.details?.status !== undefined) {
|
||||
character.setStatus(message.details?.status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2130,13 +2132,10 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
public enableMediaBehaviors() {
|
||||
const silent = this.gameMap.getCurrentProperties().get(GameMapProperties.SILENT);
|
||||
this.connection?.setSilent(!!silent);
|
||||
mediaManager.showMyCamera();
|
||||
}
|
||||
|
||||
public disableMediaBehaviors() {
|
||||
this.connection?.setSilent(true);
|
||||
mediaManager.hideMyCamera();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AvailabilityStatus } from "../../Messages/ts-proto-generated/protos/messages";
|
||||
import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures";
|
||||
|
||||
export interface PlayerInterface {
|
||||
@@ -7,7 +8,7 @@ export interface PlayerInterface {
|
||||
visitCardUrl: string | null;
|
||||
companion: string | null;
|
||||
userUuid: string;
|
||||
away: boolean;
|
||||
status: AvailabilityStatus;
|
||||
color?: string;
|
||||
outlineColor?: number;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ export class PlayerMovement {
|
||||
const y =
|
||||
(this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) +
|
||||
this.startPosition.y;
|
||||
//console.log('Computed position ', x, y)
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
|
||||
@@ -67,4 +67,20 @@ export class TexturesHelper {
|
||||
rectangleTexture.generateTexture(textureKey, width, height);
|
||||
rectangleTexture.destroy();
|
||||
}
|
||||
|
||||
public static createCircleTexture(
|
||||
scene: Phaser.Scene,
|
||||
textureKey: string,
|
||||
radius: number,
|
||||
color: number,
|
||||
outlineColor?: number,
|
||||
outlineThickness?: number
|
||||
): void {
|
||||
const circleTexture = scene.add.graphics().fillStyle(color, 1).fillCircle(radius, radius, radius);
|
||||
if (outlineColor) {
|
||||
circleTexture.lineStyle(outlineThickness ?? 1, outlineColor).strokeCircle(radius, radius, radius);
|
||||
}
|
||||
circleTexture.generateTexture(textureKey, radius * 2, radius * 2);
|
||||
circleTexture.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export class Player extends Character {
|
||||
companionTexturePromise?: CancelablePromise<string>
|
||||
) {
|
||||
super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise);
|
||||
this.statusDot.setVisible(false);
|
||||
//the current player model should be push away by other players to prevent conflict
|
||||
this.getBody().setImmovable(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user