Merge branch 'develop' of github.com:thecodingmachine/workadventure into metadataScriptingApi
This commit is contained in:
commit
5565ddd3f4
42 changed files with 1422 additions and 460 deletions
|
@ -12,6 +12,7 @@ export abstract class DirtyScene extends ResizableScene {
|
|||
private isAlreadyTracking: boolean = false;
|
||||
protected dirty:boolean = true;
|
||||
private objectListChanged:boolean = true;
|
||||
private physicsEnabled: boolean = false;
|
||||
|
||||
/**
|
||||
* Track all objects added to the scene and adds a callback each time an animation is added.
|
||||
|
@ -38,6 +39,27 @@ export abstract class DirtyScene extends ResizableScene {
|
|||
this.objectListChanged = false;
|
||||
this.dirty = false;
|
||||
});
|
||||
|
||||
this.physics.disableUpdate();
|
||||
this.events.on(Events.POST_UPDATE, () => {
|
||||
let objectMoving = false;
|
||||
for (const body of this.physics.world.bodies.entries) {
|
||||
if (body.velocity.x !== 0 || body.velocity.y !== 0) {
|
||||
this.objectListChanged = true;
|
||||
objectMoving = true;
|
||||
if (!this.physicsEnabled) {
|
||||
this.physics.enableUpdate();
|
||||
this.physicsEnabled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!objectMoving && this.physicsEnabled) {
|
||||
this.physics.disableUpdate();
|
||||
this.physicsEnabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private trackAnimation(): void {
|
||||
|
|
|
@ -52,6 +52,7 @@ import { mediaManager } from "../../WebRtc/MediaManager";
|
|||
import type { ItemFactoryInterface } from "../Items/ItemFactoryInterface";
|
||||
import type { ActionableItem } from "../Items/ActionableItem";
|
||||
import { UserInputManager } from "../UserInput/UserInputManager";
|
||||
import {soundManager} from "./SoundManager";
|
||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
||||
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
|
@ -92,7 +93,8 @@ import { PinchManager } from "../UserInput/PinchManager";
|
|||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
|
||||
import { waScaleManager } from "../Services/WaScaleManager";
|
||||
import { EmoteManager } from "./EmoteManager";
|
||||
import { peerStore} from "../../Stores/PeerStore";
|
||||
import {EmoteManager } from "./EmoteManager";
|
||||
import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
|
||||
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
|
||||
|
||||
|
@ -189,9 +191,7 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
private popUpElements : Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
||||
private originalMapUrl: string | undefined;
|
||||
private pinchManager: PinchManager | undefined;
|
||||
private physicsEnabled: boolean = true;
|
||||
private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time.
|
||||
private onVisibilityChangeCallback: () => void;
|
||||
private emoteManager!: EmoteManager;
|
||||
|
||||
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
||||
|
@ -212,7 +212,6 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
this.connectionAnswerPromise = new Promise<RoomJoinedMessageInterface>((resolve, reject): void => {
|
||||
this.connectionAnswerPromiseResolve = resolve;
|
||||
});
|
||||
this.onVisibilityChangeCallback = this.onVisibilityChange.bind(this);
|
||||
}
|
||||
|
||||
//hook preload scene
|
||||
|
@ -507,8 +506,6 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
if (!this.room.isDisconnected()) {
|
||||
this.connect();
|
||||
}
|
||||
console.log('display');
|
||||
document.addEventListener('visibilitychange', this.onVisibilityChangeCallback);
|
||||
|
||||
this.emoteManager = new EmoteManager(this);
|
||||
}
|
||||
|
@ -615,6 +612,7 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
|
||||
// When connection is performed, let's connect SimplePeer
|
||||
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic, this.playerName);
|
||||
peerStore.connectToSimplePeer(this.simplePeer);
|
||||
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
|
||||
userMessageManager.setReceiveBanListener(this.bannedUser.bind(this));
|
||||
|
||||
|
@ -632,7 +630,6 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
self.chatModeSprite.setVisible(false);
|
||||
self.openChatIcon.setVisible(false);
|
||||
audioManager.restoreVolume();
|
||||
self.onVisibilityChange();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -870,6 +867,24 @@ ${escapedMessage}
|
|||
this.userInputManager.disableControls();
|
||||
}));
|
||||
|
||||
this.iframeSubscriptionList.push(iframeListener.playSoundStream.subscribe((playSoundEvent)=>
|
||||
{
|
||||
const url = new URL(playSoundEvent.url, this.MapUrlFile);
|
||||
soundManager.playSound(this.load,this.sound,url.toString(),playSoundEvent.config);
|
||||
}))
|
||||
|
||||
this.iframeSubscriptionList.push(iframeListener.stopSoundStream.subscribe((stopSoundEvent)=>
|
||||
{
|
||||
const url = new URL(stopSoundEvent.url, this.MapUrlFile);
|
||||
soundManager.stopSound(this.sound,url.toString());
|
||||
}))
|
||||
|
||||
this.iframeSubscriptionList.push(iframeListener.loadSoundStream.subscribe((loadSoundEvent)=>
|
||||
{
|
||||
const url = new URL(loadSoundEvent.url, this.MapUrlFile);
|
||||
soundManager.loadSound(this.load,this.sound,url.toString());
|
||||
}))
|
||||
|
||||
this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(() => {
|
||||
this.userInputManager.restoreControls();
|
||||
}));
|
||||
|
@ -1000,8 +1015,6 @@ ${escapedMessage}
|
|||
for (const iframeEvents of this.iframeSubscriptionList) {
|
||||
iframeEvents.unsubscribe();
|
||||
}
|
||||
|
||||
document.removeEventListener('visibilitychange', this.onVisibilityChangeCallback);
|
||||
}
|
||||
|
||||
private removeAllRemotePlayers(): void {
|
||||
|
@ -1150,8 +1163,6 @@ ${escapedMessage}
|
|||
}
|
||||
|
||||
createCollisionWithPlayer() {
|
||||
this.physics.disableUpdate();
|
||||
this.physicsEnabled = false;
|
||||
//add collision layer
|
||||
for (const phaserLayer of this.gameMap.phaserLayers) {
|
||||
if (phaserLayer.type == "tilelayer") {
|
||||
|
@ -1294,20 +1305,7 @@ ${escapedMessage}
|
|||
update(time: number, delta: number): void {
|
||||
mediaManager.updateScene();
|
||||
this.currentTick = time;
|
||||
if (this.CurrentPlayer.isMoving()) {
|
||||
this.dirty = true;
|
||||
}
|
||||
this.CurrentPlayer.moveUser(delta);
|
||||
if (this.CurrentPlayer.isMoving()) {
|
||||
this.dirty = true;
|
||||
if (!this.physicsEnabled) {
|
||||
this.physics.enableUpdate();
|
||||
this.physicsEnabled = true;
|
||||
}
|
||||
} else if (this.physicsEnabled) {
|
||||
this.physics.disableUpdate();
|
||||
this.physicsEnabled = false;
|
||||
}
|
||||
|
||||
// Let's handle all events
|
||||
while (this.pendingEvents.length !== 0) {
|
||||
|
@ -1575,8 +1573,6 @@ ${escapedMessage}
|
|||
mediaManager.addTriggerCloseJitsiFrameButton('close-jisi', () => {
|
||||
this.stopJitsi();
|
||||
});
|
||||
|
||||
this.onVisibilityChange();
|
||||
}
|
||||
|
||||
public stopJitsi(): void {
|
||||
|
@ -1585,7 +1581,6 @@ ${escapedMessage}
|
|||
mediaManager.showGameOverlay();
|
||||
|
||||
mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi');
|
||||
this.onVisibilityChange();
|
||||
}
|
||||
|
||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||
|
@ -1625,20 +1620,4 @@ ${escapedMessage}
|
|||
waScaleManager.zoomModifier *= zoomFactor;
|
||||
this.updateCameraOffset();
|
||||
}
|
||||
|
||||
private onVisibilityChange(): void {
|
||||
// If the overlay is not displayed, we are in Jitsi. We don't need the webcam.
|
||||
if (!mediaManager.isGameOverlayVisible()) {
|
||||
mediaManager.blurCamera();
|
||||
return;
|
||||
}
|
||||
|
||||
if (document.visibilityState === 'visible') {
|
||||
mediaManager.focusCamera();
|
||||
} else {
|
||||
if (this.simplePeer.getNbConnections() === 0) {
|
||||
mediaManager.blurCamera();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
37
front/src/Phaser/Game/SoundManager.ts
Normal file
37
front/src/Phaser/Game/SoundManager.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
|
||||
import BaseSoundManager = Phaser.Sound.BaseSoundManager;
|
||||
import BaseSound = Phaser.Sound.BaseSound;
|
||||
import SoundConfig = Phaser.Types.Sound.SoundConfig;
|
||||
|
||||
class SoundManager {
|
||||
private soundPromises : Map<string,Promise<BaseSound>> = new Map<string, Promise<Phaser.Sound.BaseSound>>();
|
||||
public loadSound (loadPlugin: LoaderPlugin, soundManager : BaseSoundManager, soundUrl: string) : Promise<BaseSound> {
|
||||
let soundPromise = this.soundPromises.get(soundUrl);
|
||||
if (soundPromise !== undefined) {
|
||||
return soundPromise;
|
||||
}
|
||||
soundPromise = new Promise<BaseSound>((res) => {
|
||||
|
||||
const sound = soundManager.get(soundUrl);
|
||||
if (sound !== null) {
|
||||
return res(sound);
|
||||
}
|
||||
loadPlugin.audio(soundUrl, soundUrl);
|
||||
loadPlugin.once('filecomplete-audio-' + soundUrl, () => res(soundManager.add(soundUrl)));
|
||||
loadPlugin.start();
|
||||
});
|
||||
this.soundPromises.set(soundUrl,soundPromise);
|
||||
return soundPromise;
|
||||
}
|
||||
|
||||
public async playSound(loadPlugin: LoaderPlugin, soundManager : BaseSoundManager, soundUrl: string, config: SoundConfig|undefined) : Promise<void> {
|
||||
const sound = await this.loadSound(loadPlugin,soundManager,soundUrl);
|
||||
if (config === undefined) sound.play();
|
||||
else sound.play(config);
|
||||
}
|
||||
|
||||
public stopSound(soundManager : BaseSoundManager,soundUrl : string){
|
||||
soundManager.get(soundUrl).stop();
|
||||
}
|
||||
}
|
||||
export const soundManager = new SoundManager();
|
|
@ -10,6 +10,14 @@ import {PinchManager} from "../UserInput/PinchManager";
|
|||
import Zone = Phaser.GameObjects.Zone;
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {
|
||||
audioConstraintStore,
|
||||
enableCameraSceneVisibilityStore,
|
||||
localStreamStore,
|
||||
mediaStreamConstraintsStore,
|
||||
videoConstraintStore
|
||||
} from "../../Stores/MediaStore";
|
||||
import type {Unsubscriber} from "svelte/store";
|
||||
|
||||
export const EnableCameraSceneName = "EnableCameraScene";
|
||||
enum LoginTextures {
|
||||
|
@ -40,6 +48,7 @@ export class EnableCameraScene extends ResizableScene {
|
|||
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
|
||||
private mobileTapZone!: Zone;
|
||||
private localStreamStoreUnsubscriber!: Unsubscriber;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
|
@ -119,9 +128,20 @@ export class EnableCameraScene extends ResizableScene {
|
|||
|
||||
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').classList.add('active');
|
||||
|
||||
const mediaPromise = mediaManager.getCamera();
|
||||
this.localStreamStoreUnsubscriber = localStreamStore.subscribe((result) => {
|
||||
if (result.type === 'error') {
|
||||
// TODO: proper handling of the error
|
||||
throw result.error;
|
||||
}
|
||||
|
||||
this.getDevices();
|
||||
if (result.stream !== null) {
|
||||
this.setupStream(result.stream);
|
||||
}
|
||||
});
|
||||
/*const mediaPromise = mediaManager.getCamera();
|
||||
mediaPromise.then(this.getDevices.bind(this));
|
||||
mediaPromise.then(this.setupStream.bind(this));
|
||||
mediaPromise.then(this.setupStream.bind(this));*/
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', this.nextCam.bind(this));
|
||||
this.input.keyboard.on('keydown-LEFT', this.previousCam.bind(this));
|
||||
|
@ -133,6 +153,8 @@ export class EnableCameraScene extends ResizableScene {
|
|||
this.add.existing(this.soundMeterSprite);
|
||||
|
||||
this.onResize();
|
||||
|
||||
enableCameraSceneVisibilityStore.showEnableCameraScene();
|
||||
}
|
||||
|
||||
private previousCam(): void {
|
||||
|
@ -140,7 +162,9 @@ export class EnableCameraScene extends ResizableScene {
|
|||
return;
|
||||
}
|
||||
this.cameraSelected--;
|
||||
mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
|
||||
videoConstraintStore.setDeviceId(this.camerasList[this.cameraSelected].deviceId);
|
||||
|
||||
//mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
|
||||
}
|
||||
|
||||
private nextCam(): void {
|
||||
|
@ -148,8 +172,10 @@ export class EnableCameraScene extends ResizableScene {
|
|||
return;
|
||||
}
|
||||
this.cameraSelected++;
|
||||
videoConstraintStore.setDeviceId(this.camerasList[this.cameraSelected].deviceId);
|
||||
|
||||
// TODO: the change of camera should be OBSERVED (reactive)
|
||||
mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
|
||||
//mediaManager.setCamera(this.camerasList[this.cameraSelected].deviceId).then(this.setupStream.bind(this));
|
||||
}
|
||||
|
||||
private previousMic(): void {
|
||||
|
@ -157,7 +183,8 @@ export class EnableCameraScene extends ResizableScene {
|
|||
return;
|
||||
}
|
||||
this.microphoneSelected--;
|
||||
mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
|
||||
audioConstraintStore.setDeviceId(this.microphonesList[this.microphoneSelected].deviceId);
|
||||
//mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
|
||||
}
|
||||
|
||||
private nextMic(): void {
|
||||
|
@ -165,8 +192,9 @@ export class EnableCameraScene extends ResizableScene {
|
|||
return;
|
||||
}
|
||||
this.microphoneSelected++;
|
||||
audioConstraintStore.setDeviceId(this.microphonesList[this.microphoneSelected].deviceId);
|
||||
// TODO: the change of camera should be OBSERVED (reactive)
|
||||
mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
|
||||
//mediaManager.setMicrophone(this.microphonesList[this.microphoneSelected].deviceId).then(this.setupStream.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,15 +288,20 @@ export class EnableCameraScene extends ResizableScene {
|
|||
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
||||
this.soundMeter.stop();
|
||||
|
||||
mediaManager.stopCamera();
|
||||
mediaManager.stopMicrophone();
|
||||
enableCameraSceneVisibilityStore.hideEnableCameraScene();
|
||||
this.localStreamStoreUnsubscriber();
|
||||
//mediaManager.stopCamera();
|
||||
//mediaManager.stopMicrophone();
|
||||
|
||||
this.scene.sleep(EnableCameraSceneName)
|
||||
this.scene.sleep(EnableCameraSceneName);
|
||||
gameManager.goToStartingMap(this.scene);
|
||||
}
|
||||
|
||||
private async getDevices() {
|
||||
// TODO: switch this in a store.
|
||||
const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices();
|
||||
this.microphonesList = [];
|
||||
this.camerasList = [];
|
||||
for (const mediaDeviceInfo of mediaDeviceInfos) {
|
||||
if (mediaDeviceInfo.kind === 'audioinput') {
|
||||
this.microphonesList.push(mediaDeviceInfo);
|
||||
|
|
|
@ -2,6 +2,8 @@ import {mediaManager} from "../../WebRtc/MediaManager";
|
|||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {DirtyScene} from "../Game/DirtyScene";
|
||||
import {get} from "svelte/store";
|
||||
import {requestedCameraState, requestedMicrophoneState} from "../../Stores/MediaStore";
|
||||
|
||||
export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
|
||||
const helpCameraSettings = 'helpCameraSettings';
|
||||
|
@ -41,7 +43,7 @@ export class HelpCameraSettingsScene extends DirtyScene {
|
|||
}
|
||||
});
|
||||
|
||||
if(!localUserStore.getHelpCameraSettingsShown() && (!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video)){
|
||||
if(!localUserStore.getHelpCameraSettingsShown() && (!get(requestedMicrophoneState) || !get(requestedCameraState))){
|
||||
this.openHelpCameraSettingsOpened();
|
||||
localUserStore.setHelpCameraSettingsShown();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {menuIconVisible} from "../../Stores/MenuStore";
|
|||
import { HtmlUtils } from '../../WebRtc/HtmlUtils';
|
||||
import { iframeListener } from '../../Api/IframeListener';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { videoConstraintStore } from "../../Stores/MediaStore";
|
||||
|
||||
export const MenuSceneName = 'MenuScene';
|
||||
const gameMenuKey = 'gameMenu';
|
||||
|
@ -356,7 +357,7 @@ export class MenuScene extends Phaser.Scene {
|
|||
if (valueVideo !== this.videoQualityValue) {
|
||||
this.videoQualityValue = valueVideo;
|
||||
localUserStore.setVideoQualityValue(valueVideo);
|
||||
mediaManager.updateCameraQuality(valueVideo);
|
||||
videoConstraintStore.setFrameRate(valueVideo);
|
||||
}
|
||||
this.closeGameQualityMenu();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import {PlayerAnimationDirections} from "./Animation";
|
|||
import type {GameScene} from "../Game/GameScene";
|
||||
import {UserInputEvent, UserInputManager} from "../UserInput/UserInputManager";
|
||||
import {Character} from "../Entity/Character";
|
||||
import {userMovingStore} from "../../Stores/GameStore";
|
||||
import {RadialMenu, RadialMenuClickEvent, RadialMenuItem} from "../Components/RadialMenu";
|
||||
|
||||
export const hasMovedEventName = "hasMoved";
|
||||
|
@ -86,6 +87,7 @@ export class Player extends Character {
|
|||
this.previousDirection = direction;
|
||||
}
|
||||
this.wasMoving = moving;
|
||||
userMovingStore.set(moving);
|
||||
}
|
||||
|
||||
public isMoving(): boolean {
|
||||
|
@ -99,7 +101,7 @@ export class Player extends Character {
|
|||
this.openEmoteMenu(emotes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
isClickable(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
@ -113,13 +115,13 @@ export class Player extends Character {
|
|||
this.playEmote(item.name);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
closeEmoteMenu(): void {
|
||||
if (!this.emoteMenu) return;
|
||||
this.emoteMenu.destroy();
|
||||
this.emoteMenu = null;
|
||||
}
|
||||
|
||||
|
||||
destroy() {
|
||||
this.scene.events.removeListener('postupdate', this.updateListener);
|
||||
super.destroy();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue