merged develop

This commit is contained in:
Piotr 'pwh' Hanusiak
2022-04-12 15:22:40 +02:00
176 changed files with 1376 additions and 2553 deletions
-4
View File
@@ -1,9 +1,7 @@
import ImageFrameConfig = Phaser.Types.Loader.FileTypes.ImageFrameConfig;
import { DirtyScene } from "../Game/DirtyScene";
import { gameManager } from "../Game/GameManager";
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
import CancelablePromise from "cancelable-promise";
import Image = Phaser.GameObjects.Image;
import Texture = Phaser.Textures.Texture;
const TextName: string = "Loading...";
@@ -35,8 +33,6 @@ export class Loader {
const logoResource = gameManager.currentStartedRoom.loadingLogo ?? "static/images/logo.png";
this.logoNameIndex = "logoLoading" + logoResource;
const loadingBarWidth: number = Math.floor(this.scene.game.renderer.width / 3);
//add loading if logo image until logo image is ready
this.loadingText = this.scene.add.text(
this.scene.game.renderer.width / 2,
@@ -0,0 +1,65 @@
import { Easing } from "../../types";
export class PlayerStatusDot extends Phaser.GameObjects.Container {
private graphics: Phaser.GameObjects.Graphics;
private away: boolean;
private readonly COLORS = {
// online: 0x00ff00,
// away: 0xffff00,
online: 0x8cc43f,
onlineOutline: 0x427a25,
away: 0xf5931e,
awayOutline: 0x875d13,
};
constructor(scene: Phaser.Scene, x: number, y: number) {
super(scene, x, y);
this.away = false;
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) {
return;
}
this.away = away;
if (instant) {
this.redraw();
} else {
this.playStatusChangeAnimation();
}
}
private playStatusChangeAnimation(): void {
this.scale = 1;
this.scene.tweens.add({
targets: [this],
duration: 200,
yoyo: true,
ease: Easing.BackEaseIn,
scale: 0,
onYoyo: () => {
this.redraw();
},
onComplete: () => {
this.scale = 1;
},
});
}
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);
}
}
-1
View File
@@ -1,6 +1,5 @@
import type { ITiledMapObject } from "../Map/ITiledMap";
import type { GameScene } from "../Game/GameScene";
import { type } from "os";
import { GameMapProperties } from "../Game/GameMapProperties";
export class TextUtils {
+9 -7
View File
@@ -1,9 +1,4 @@
import {
AnimationData,
getPlayerAnimations,
PlayerAnimationDirections,
PlayerAnimationTypes,
} from "../Player/Animation";
import { getPlayerAnimations, PlayerAnimationDirections, PlayerAnimationTypes } from "../Player/Animation";
import { SpeechBubble } from "./SpeechBubble";
import Text = Phaser.GameObjects.Text;
import Container = Phaser.GameObjects.Container;
@@ -24,6 +19,7 @@ import type { OutlineableInterface } from "../Game/OutlineableInterface";
import type CancelablePromise from "cancelable-promise";
import { TalkIcon } from "../Components/TalkIcon";
import { Deferred } from "ts-deferred";
import { PlayerStatusDot } from "../Components/PlayerStatusDot";
const playerNameY = -25;
const interactiveRadius = 35;
@@ -32,6 +28,7 @@ export abstract class Character extends Container implements OutlineableInterfac
private bubble: SpeechBubble | null = null;
private readonly playerNameText: Text;
private readonly talkIcon: TalkIcon;
protected readonly statusDot: PlayerStatusDot;
public playerName: string;
public sprites: Map<string, Sprite>;
protected lastDirection: PlayerAnimationDirections = PlayerAnimationDirections.Down;
@@ -137,7 +134,8 @@ export abstract class Character extends Container implements OutlineableInterfac
});
}
this.playerNameText.setOrigin(0.5).setDepth(DEPTH_INGAME_TEXT_INDEX);
this.add(this.playerNameText);
this.statusDot = new PlayerStatusDot(scene, this.playerNameText.getLeftCenter().x - 6, playerNameY - 1);
this.add([this.playerNameText, this.statusDot]);
this.setClickable(isClickable);
@@ -238,6 +236,10 @@ 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 addCompanion(name: string, texturePromise?: CancelablePromise<string>): void {
if (typeof texturePromise !== "undefined") {
this.companion = new Companion(this.scene, this.x, this.y, name, texturePromise);
@@ -1,6 +1,5 @@
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
import type { CharacterTexture } from "../../Connexion/LocalUser";
import { BodyResourceDescriptionInterface, mapLayerToLevel, PlayerTextures, PlayerTexturesKey } from "./PlayerTextures";
import { BodyResourceDescriptionInterface, PlayerTextures, PlayerTexturesKey } from "./PlayerTextures";
import CancelablePromise from "cancelable-promise";
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
import Texture = Phaser.Textures.Texture;
+2
View File
@@ -97,6 +97,7 @@ export class CameraManager extends Phaser.Events.EventEmitter {
});
return;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.camera.pan(setTo.x, setTo.y, duration, Easing.SineEaseOut, true, (camera, progress, x, y) => {
if (this.cameraMode === CameraMode.Positioned) {
this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange;
@@ -138,6 +139,7 @@ export class CameraManager extends Phaser.Events.EventEmitter {
this.emit(CameraManagerEvent.CameraUpdate, this.getCameraUpdateEventData());
return;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.camera.pan(focusOn.x, focusOn.y, duration, Easing.SineEaseOut, true, (camera, progress, x, y) => {
this.waScaleManager.zoomModifier = currentZoomModifier + progress * zoomModifierChange;
if (progress === 1) {
@@ -223,7 +223,7 @@ height,*/
}
close(): void {
for (const [key, website] of this.embeddedWebsites) {
for (const website of this.embeddedWebsites.values()) {
if (website.allowApi) {
iframeListener.unregisterIframe(website.iframe);
}
-2
View File
@@ -1,6 +1,4 @@
import { SKIP_RENDER_OPTIMIZATIONS } from "../../Enum/EnvironmentVariable";
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
import { waScaleManager } from "../Services/WaScaleManager";
import { ResizableScene } from "../Login/ResizableScene";
const Events = Phaser.Core.Events;
@@ -124,7 +124,7 @@ export class GameMapPropertiesListener {
}
});
this.gameMap.onPropertyChange(GameMapProperties.EXIT_SCENE_URL, (newValue, oldValue) => {
this.gameMap.onPropertyChange(GameMapProperties.EXIT_SCENE_URL, (newValue) => {
if (newValue) {
this.scene
.onMapExit(
@@ -142,7 +142,7 @@ export class GameMapPropertiesListener {
}
});
this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => {
this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue) => {
if (newValue) {
this.scene
.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString()))
@@ -154,7 +154,7 @@ export class GameMapPropertiesListener {
}
});
this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue, oldValue) => {
this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue) => {
if (newValue === undefined || newValue === false || newValue === "") {
this.scene.connection?.setSilent(false);
this.scene.CurrentPlayer.noSilent();
@@ -174,7 +174,7 @@ export class GameMapPropertiesListener {
});
// TODO: This legacy property should be removed at some point
this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO_LOOP, (newValue, oldValue) => {
this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO_LOOP, (newValue) => {
newValue === undefined
? audioManagerFileStore.unloadAudio()
: audioManagerFileStore.playAudio(newValue, this.scene.getMapDirUrl(), undefined, true);
+54 -18
View File
@@ -71,7 +71,7 @@ import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStor
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
import { playersStore } from "../../Stores/PlayersStore";
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
import { userIsAdminStore } from "../../Stores/GameStore";
import { jitsiParticipantsCountStore, userIsAdminStore, userIsJitsiDominantSpeakerStore } from "../../Stores/GameStore";
import { contactPageStore } from "../../Stores/MenuStore";
import type { WasCameraUpdatedEvent } from "../../Api/Events/WasCameraUpdatedEvent";
import { audioManagerFileStore } from "../../Stores/AudioManagerStore";
@@ -97,11 +97,11 @@ import { startLayerNamesStore } from "../../Stores/StartLayerNamesStore";
import { JitsiCoWebsite } from "../../WebRtc/CoWebsite/JitsiCoWebsite";
import { SimpleCoWebsite } from "../../WebRtc/CoWebsite/SimpleCoWebsite";
import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite";
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";
import { privacyShutdownStore } from "../../Stores/PrivacyShutdownStore";
export interface GameSceneInitInterface {
initPosition: PointInterface | null;
reconnecting: boolean;
@@ -177,7 +177,9 @@ export class GameScene extends DirtyScene {
private localVolumeStoreUnsubscriber: Unsubscriber | undefined;
private followUsersColorStoreUnsubscribe!: Unsubscriber;
private currentPlayerGroupIdStoreUnsubscribe!: Unsubscriber;
private privacyShutdownStoreUnsubscribe!: Unsubscriber;
private userIsJitsiDominantSpeakerStoreUnsubscriber!: Unsubscriber;
private jitsiParticipantsCountStoreUnsubscriber!: Unsubscriber;
private biggestAvailableAreaStoreUnsubscribe!: () => void;
MapUrlFile: string;
@@ -187,7 +189,7 @@ export class GameScene extends DirtyScene {
currentTick!: number;
lastSentTick!: number; // The last tick at which a position was sent.
lastMoveEventSent: HasPlayerMovedEvent = {
direction: "",
direction: "down",
moving: false,
x: -1000,
y: -1000,
@@ -221,6 +223,8 @@ export class GameScene extends DirtyScene {
private firstCameraUpdateSent: boolean = false;
private showVoiceIndicatorChangeMessageSent: boolean = false;
private currentPlayerGroupId?: number;
private jitsiDominantSpeaker: boolean = false;
private jitsiParticipantsCount: number = 0;
public readonly superLoad: SuperLoaderPlugin;
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
@@ -648,16 +652,7 @@ export class GameScene extends DirtyScene {
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;
}
this.tryChangeShowVoiceIndicatorState(volume > talkIconVolumeTreshold);
});
}
} else {
@@ -673,6 +668,18 @@ export class GameScene extends DirtyScene {
oldPeersNumber = peers.size;
});
this.userIsJitsiDominantSpeakerStoreUnsubscriber = userIsJitsiDominantSpeakerStore.subscribe(
(dominantSpeaker) => {
this.jitsiDominantSpeaker = dominantSpeaker;
this.tryChangeShowVoiceIndicatorState(this.jitsiDominantSpeaker && this.jitsiParticipantsCount > 1);
}
);
this.jitsiParticipantsCountStoreUnsubscriber = jitsiParticipantsCountStore.subscribe((participantsCount) => {
this.jitsiParticipantsCount = participantsCount;
this.tryChangeShowVoiceIndicatorState(this.jitsiDominantSpeaker && this.jitsiParticipantsCount > 1);
});
this.emoteUnsubscribe = emoteStore.subscribe((emote) => {
if (emote) {
this.CurrentPlayer?.playEmote(emote.url);
@@ -699,6 +706,10 @@ export class GameScene extends DirtyScene {
}
});
this.privacyShutdownStoreUnsubscribe = privacyShutdownStore.subscribe((away) => {
this.connection?.emitPlayerAway(away);
});
Promise.all([
this.connectionAnswerPromiseDeferred.promise as Promise<unknown>,
...scriptPromises,
@@ -757,6 +768,7 @@ export class GameScene extends DirtyScene {
characterLayers: message.characterLayers,
name: message.name,
position: message.position,
away: message.away,
visitCardUrl: message.visitCardUrl,
companion: message.companion,
userUuid: message.userUuid,
@@ -1010,6 +1022,7 @@ ${escapedMessage}
}, 100);
id = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const button of openPopupEvent.buttons) {
const button = HtmlUtils.getElementByIdOrFail<HTMLButtonElement>(
`popup-${openPopupEvent.popupId}-${id}`
@@ -1268,7 +1281,7 @@ ${escapedMessage}
await this.connectionAnswerPromiseDeferred.promise;
return {
mapUrl: this.MapUrlFile,
startLayerName: this.startPositionCalculator.startLayerName,
startLayerName: this.startPositionCalculator.startLayerName ?? undefined,
uuid: localUserStore.getLocalUser()?.uuid,
nickname: this.playerName,
language: get(locale),
@@ -1377,6 +1390,7 @@ ${escapedMessage}
break;
}
default: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _exhaustiveCheck: never = event.target;
}
}
@@ -1396,7 +1410,7 @@ ${escapedMessage}
this.connection?.emitPlayerOutlineColor(color);
});
iframeListener.registerAnswerer("removePlayerOutline", (message) => {
iframeListener.registerAnswerer("removePlayerOutline", () => {
this.CurrentPlayer.removeApiOutlineColor();
this.connection?.emitPlayerOutlineColor(null);
});
@@ -1539,7 +1553,10 @@ ${escapedMessage}
this.emoteUnsubscribe();
this.emoteMenuUnsubscribe();
this.followUsersColorStoreUnsubscribe();
this.privacyShutdownStoreUnsubscribe();
this.biggestAvailableAreaStoreUnsubscribe();
this.userIsJitsiDominantSpeakerStoreUnsubscriber();
this.jitsiParticipantsCountStoreUnsubscriber();
iframeListener.unregisterAnswerer("getState");
iframeListener.unregisterAnswerer("loadTileset");
iframeListener.unregisterAnswerer("getMapData");
@@ -1676,6 +1693,7 @@ ${escapedMessage}
private createCollisionWithPlayer() {
//add collision layer
for (const phaserLayer of this.gameMap.phaserLayers) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.physics.add.collider(this.CurrentPlayer, phaserLayer, (object1: GameObject, object2: GameObject) => {
//this.CurrentPlayer.say("Collision with layer : "+ (object2 as Tile).layer.name)
});
@@ -1726,9 +1744,11 @@ ${escapedMessage}
emoteMenuStore.openEmoteMenu();
}
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.CurrentPlayer.on(Phaser.Input.Events.POINTER_OVER, (pointer: Phaser.Input.Pointer) => {
this.CurrentPlayer.pointerOverOutline(0x365dff);
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.CurrentPlayer.on(Phaser.Input.Events.POINTER_OUT, (pointer: Phaser.Input.Pointer) => {
this.CurrentPlayer.pointerOutOutline();
});
@@ -1830,6 +1850,7 @@ ${escapedMessage}
break;
}
default: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const tmp: never = event;
}
}
@@ -1909,6 +1930,9 @@ ${escapedMessage}
if (addPlayerData.outlineColor !== undefined) {
player.setApiOutlineColor(addPlayerData.outlineColor);
}
if (addPlayerData.away !== undefined) {
player.setAwayStatus(addPlayerData.away, true);
}
this.MapPlayers.add(player);
this.MapPlayersByKey.set(player.userId, player);
player.updatePosition(addPlayerData.position);
@@ -1938,6 +1962,17 @@ ${escapedMessage}
});
}
private tryChangeShowVoiceIndicatorState(show: boolean): void {
this.CurrentPlayer.showTalkIcon(show);
if (this.showVoiceIndicatorChangeMessageSent && !show) {
this.connection?.emitPlayerShowVoiceIndicator(false);
this.showVoiceIndicatorChangeMessageSent = false;
} else if (!this.showVoiceIndicatorChangeMessageSent && show) {
this.connection?.emitPlayerShowVoiceIndicator(true);
this.showVoiceIndicatorChangeMessageSent = true;
}
}
private doRemovePlayer(userId: number) {
const player = this.MapPlayersByKey.get(userId);
if (player === undefined) {
@@ -1977,8 +2012,6 @@ ${escapedMessage}
this.currentTick,
{
...message.position,
oldX: undefined,
oldY: undefined,
},
this.currentTick + POSITION_DELAY
);
@@ -2049,6 +2082,9 @@ ${escapedMessage}
if (message.details?.showVoiceIndicator !== undefined) {
character.showTalkIcon(message.details?.showVoiceIndicator);
}
if (message.details?.away !== undefined) {
character.setAwayStatus(message.details?.away);
}
}
/**
+1
View File
@@ -7,6 +7,7 @@ export interface PlayerInterface {
visitCardUrl: string | null;
companion: string | null;
userUuid: string;
away: boolean;
color?: string;
outlineColor?: number;
}
+13 -10
View File
@@ -4,14 +4,13 @@ import type { ITiledMapObject } from "../../Map/ITiledMap";
import type { ItemFactoryInterface } from "../ItemFactoryInterface";
import type { GameScene } from "../../Game/GameScene";
import { ActionableItem } from "../ActionableItem";
import * as tg from "generic-type-guard";
import { z } from "zod";
const isComputerState = new tg.IsInterface()
.withProperties({
status: tg.isString,
})
.get();
type ComputerState = tg.GuardedType<typeof isComputerState>;
export const isComputerState = z.object({
status: z.string(),
});
export type ComputerState = z.infer<typeof isComputerState>;
let state: ComputerState = {
status: "off",
@@ -55,10 +54,14 @@ export default {
},
factory: (scene: GameScene, object: ITiledMapObject, initState: unknown): ActionableItem => {
if (initState !== undefined) {
if (!isComputerState(initState)) {
throw new Error("Invalid state received for computer object");
try {
state = isComputerState.parse(initState);
} catch (err) {
if (err instanceof z.ZodError) {
console.error(err.issues);
}
throw new Error(`Invalid state received for computer object`);
}
state = initState;
}
const computer = new Sprite(scene, object.x, object.y, "computer");
+1
View File
@@ -112,6 +112,7 @@ export class CustomizeScene extends AbstractCharacterScene {
this.onResize();
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public update(time: number, dt: number): void {
this.customWokaPreviewer.update();
}
+1
View File
@@ -13,5 +13,6 @@ export class EmptyScene extends Scene {
create() {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(time: number, delta: number): void {}
}
+1 -1
View File
@@ -1,7 +1,6 @@
import { gameManager } from "../Game/GameManager";
import { ResizableScene } from "./ResizableScene";
import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
import { localUserStore } from "../../Connexion/LocalUserStore";
import { analyticsClient } from "../../Administration/AnalyticsClient";
export const EnableCameraSceneName = "EnableCameraScene";
@@ -25,6 +24,7 @@ export class EnableCameraScene extends ResizableScene {
public onResize(): void {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(time: number, delta: number): void {}
public login(): void {
+1
View File
@@ -49,6 +49,7 @@ export class LoginScene extends ResizableScene {
loginSceneVisibleStore.set(false);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(time: number, delta: number): void {}
public onResize(): void {}
+1 -1
View File
@@ -28,7 +28,7 @@ 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);
}
@@ -1,6 +1,5 @@
import { TextField } from "../Components/TextField";
import Image = Phaser.GameObjects.Image;
import Sprite = Phaser.GameObjects.Sprite;
import LL from "../../i18n/i18n-svelte";
import { get } from "svelte/store";
+1 -1
View File
@@ -86,7 +86,7 @@ export class WaScaleManager {
const { width: gameWidth, height: gameHeight } = coWebsiteManager.getGameSize();
const devicePixelRatio = window.devicePixelRatio ?? 1;
const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({
const { real: realSize } = this.hdpiManager.getOptimalGameSize({
width: gameWidth * devicePixelRatio,
height: gameHeight * devicePixelRatio,
});
@@ -16,6 +16,7 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface {
gameObjects: Phaser.GameObjects.GameObject[],
deltaX: number,
deltaY: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
deltaZ: number
): void {
this.gameScene.zoomByFactor(1 - (deltaY / 53) * 0.1);
@@ -43,13 +44,14 @@ export class GameSceneUserInputHandler implements UserInputHandlerInterface {
.then((path) => {
// Remove first step as it is for the tile we are currently standing on
path.shift();
this.gameScene.CurrentPlayer.setPathToFollow(path).catch((reason) => {});
this.gameScene.CurrentPlayer.setPathToFollow(path).catch(() => {});
})
.catch((reason) => {
console.warn(reason);
});
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public handlePointerDownEvent(pointer: Phaser.Input.Pointer, gameObjects: Phaser.GameObjects.GameObject[]): void {}
public handleSpaceKeyUpEvent(event: Event): Event {