Merge branch 'develop' of github.com:thecodingmachine/workadventure into metadataScriptingApi
This commit is contained in:
commit
2ee62c9e9e
84 changed files with 2218 additions and 1648 deletions
|
@ -1,5 +1,5 @@
|
|||
import {PointInterface} from "../../Connexion/ConnexionModels";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
import type {PointInterface} from "../../Connexion/ConnexionModels";
|
||||
import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
|
||||
export interface AddPlayerInterface {
|
||||
userId: number;
|
||||
|
|
|
@ -2,6 +2,8 @@ import {ResizableScene} from "../Login/ResizableScene";
|
|||
import GameObject = Phaser.GameObjects.GameObject;
|
||||
import Events = Phaser.Scenes.Events;
|
||||
import AnimationEvents = Phaser.Animations.Events;
|
||||
import StructEvents = Phaser.Structs.Events;
|
||||
import {SKIP_RENDER_OPTIMIZATIONS} from "../../Enum/EnvironmentVariable";
|
||||
|
||||
/**
|
||||
* A scene that can track its dirty/pristine state.
|
||||
|
@ -18,17 +20,16 @@ export abstract class DirtyScene extends ResizableScene {
|
|||
* Note: this does not work with animations from sprites inside containers.
|
||||
*/
|
||||
protected trackDirtyAnims(): void {
|
||||
if (this.isAlreadyTracking) {
|
||||
if (this.isAlreadyTracking || SKIP_RENDER_OPTIMIZATIONS) {
|
||||
return;
|
||||
}
|
||||
this.isAlreadyTracking = true;
|
||||
const trackAnimationFunction = this.trackAnimation.bind(this);
|
||||
this.events.on(Events.ADDED_TO_SCENE, (gameObject: GameObject) => {
|
||||
this.sys.updateList.on(StructEvents.PROCESS_QUEUE_ADD, (gameObject: GameObject) => {
|
||||
this.objectListChanged = true;
|
||||
gameObject.on(AnimationEvents.ANIMATION_UPDATE, trackAnimationFunction);
|
||||
});
|
||||
|
||||
this.events.on(Events.REMOVED_FROM_SCENE, (gameObject: GameObject) => {
|
||||
this.sys.updateList.on(StructEvents.PROCESS_QUEUE_REMOVE, (gameObject: GameObject) => {
|
||||
this.objectListChanged = true;
|
||||
gameObject.removeListener(AnimationEvents.ANIMATION_UPDATE, trackAnimationFunction);
|
||||
});
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
|
@ -5,8 +10,27 @@ const Events = Phaser.Core.Events;
|
|||
* It comes with an optimization to skip rendering.
|
||||
*
|
||||
* Beware, the "step" function might vary in future versions of Phaser.
|
||||
*
|
||||
* It also automatically calls "onResize" on any scenes extending ResizableScene.
|
||||
*/
|
||||
export class Game extends Phaser.Game {
|
||||
|
||||
private _isDirty = false;
|
||||
|
||||
|
||||
constructor(GameConfig: Phaser.Types.Core.GameConfig) {
|
||||
super(GameConfig);
|
||||
|
||||
window.addEventListener('resize', (event) => {
|
||||
// Let's trigger the onResize method of any active scene that is a ResizableScene
|
||||
for (const scene of this.scene.getScenes(true)) {
|
||||
if (scene instanceof ResizableScene) {
|
||||
scene.onResize(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public step(time: number, delta: number)
|
||||
{
|
||||
// @ts-ignore
|
||||
|
@ -35,7 +59,7 @@ export class Game extends Phaser.Game {
|
|||
eventEmitter.emit(Events.POST_STEP, time, delta);
|
||||
|
||||
// This "if" is the changed introduced by the new "Game" class to avoid rendering unnecessarily.
|
||||
if (this.isDirty()) {
|
||||
if (SKIP_RENDER_OPTIMIZATIONS || this.isDirty()) {
|
||||
const renderer = this.renderer;
|
||||
|
||||
// Run the Pre-render (clearing the canvas, setting background colors, etc)
|
||||
|
@ -62,6 +86,11 @@ export class Game extends Phaser.Game {
|
|||
}
|
||||
|
||||
private isDirty(): boolean {
|
||||
if (this._isDirty) {
|
||||
this._isDirty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Loop through the scenes in forward order
|
||||
for (let i = 0; i < this.scene.scenes.length; i++)
|
||||
{
|
||||
|
@ -85,4 +114,11 @@ export class Game extends Phaser.Game {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the game as needing to be redrawn.
|
||||
*/
|
||||
public markDirty(): void {
|
||||
this._isDirty = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {GameScene} from "./GameScene";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {Room} from "../../Connexion/Room";
|
||||
import type {Room} from "../../Connexion/Room";
|
||||
import {MenuScene, MenuSceneName} from "../Menu/MenuScene";
|
||||
import {HelpCameraSettingsScene, HelpCameraSettingsSceneName} from "../Menu/HelpCameraSettingsScene";
|
||||
import {LoginSceneName} from "../Login/LoginScene";
|
||||
|
@ -24,7 +24,7 @@ export class GameManager {
|
|||
private companion: string|null;
|
||||
private startRoom!:Room;
|
||||
currentGameSceneName: string|null = null;
|
||||
|
||||
|
||||
constructor() {
|
||||
this.playerName = localUserStore.getName();
|
||||
this.characterLayers = localUserStore.getCharacterLayers();
|
||||
|
@ -65,7 +65,7 @@ export class GameManager {
|
|||
return this.characterLayers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
setCompanion(companion: string|null): void {
|
||||
this.companion = companion;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ export class GameManager {
|
|||
scenePlugin.launch(MenuSceneName);
|
||||
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
||||
}
|
||||
|
||||
|
||||
public gameSceneIsCreated(scene: GameScene) {
|
||||
this.currentGameSceneName = scene.scene.key;
|
||||
const menuScene: MenuScene = scene.scene.get(MenuSceneName) as MenuScene;
|
||||
|
@ -125,7 +125,7 @@ export class GameManager {
|
|||
scene.scene.run(fallbackSceneName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public getCurrentGameScene(scene: Phaser.Scene): GameScene {
|
||||
if (this.currentGameSceneName === null) throw 'No current scene id set!';
|
||||
return scene.scene.get(this.currentGameSceneName) as GameScene
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {ITiledMap, ITiledMapLayer, ITiledMapTileLayer} from "../Map/ITiledMap";
|
||||
import type {ITiledMap, ITiledMapLayer, ITiledMapTileLayer} from "../Map/ITiledMap";
|
||||
import { flattenGroupLayersMap } from "../Map/LayersFlattener";
|
||||
|
||||
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {gameManager, HasMovedEvent} from "./GameManager";
|
||||
import {
|
||||
import type {
|
||||
GroupCreatedUpdatedMessageInterface,
|
||||
MessageUserJoined,
|
||||
MessageUserMovedInterface,
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
MAX_PER_GROUP,
|
||||
POSITION_DELAY,
|
||||
} from "../../Enum/EnvironmentVariable";
|
||||
import {
|
||||
import type {
|
||||
ITiledMap,
|
||||
ITiledMapLayer,
|
||||
ITiledMapLayerProperty,
|
||||
|
@ -25,7 +25,7 @@ import {
|
|||
ITiledMapTileLayer,
|
||||
ITiledTileSet
|
||||
} from "../Map/ITiledMap";
|
||||
import {AddPlayerInterface} from "./AddPlayerInterface";
|
||||
import type {AddPlayerInterface} from "./AddPlayerInterface";
|
||||
import {PlayerAnimationDirections} from "../Player/Animation";
|
||||
import {PlayerMovement} from "./PlayerMovement";
|
||||
import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator";
|
||||
|
@ -49,13 +49,13 @@ import {
|
|||
import {GameMap} from "./GameMap";
|
||||
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager";
|
||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {ItemFactoryInterface} from "../Items/ItemFactoryInterface";
|
||||
import {ActionableItem} from "../Items/ActionableItem";
|
||||
import type {ItemFactoryInterface} from "../Items/ItemFactoryInterface";
|
||||
import type {ActionableItem} from "../Items/ActionableItem";
|
||||
import {UserInputManager} from "../UserInput/UserInputManager";
|
||||
import {UserMovedMessage} from "../../Messages/generated/messages_pb";
|
||||
import type {UserMovedMessage} from "../../Messages/generated/messages_pb";
|
||||
import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {RoomConnection} from "../../Connexion/RoomConnection";
|
||||
import type {RoomConnection} from "../../Connexion/RoomConnection";
|
||||
import {GlobalMessageManager} from "../../Administration/GlobalMessageManager";
|
||||
import {userMessageManager} from "../../Administration/UserMessageManager";
|
||||
import {ConsoleGlobalMessageManager} from "../../Administration/ConsoleGlobalMessageManager";
|
||||
|
@ -80,7 +80,7 @@ import CanvasTexture = Phaser.Textures.CanvasTexture;
|
|||
import GameObject = Phaser.GameObjects.GameObject;
|
||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||
import DOMElement = Phaser.GameObjects.DOMElement;
|
||||
import {Subscription} from "rxjs";
|
||||
import type {Subscription} from "rxjs";
|
||||
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
|
||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import RenderTexture = Phaser.GameObjects.RenderTexture;
|
||||
|
@ -152,7 +152,7 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
private GlobalMessageManager!: GlobalMessageManager;
|
||||
public ConsoleGlobalMessageManager!: ConsoleGlobalMessageManager;
|
||||
private connectionAnswerPromise: Promise<RoomJoinedMessageInterface>;
|
||||
private connectionAnswerPromiseResolve!: (value?: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>) => void;
|
||||
private connectionAnswerPromiseResolve!: (value: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>) => void;
|
||||
// A promise that will resolve when the "create" method is called (signaling loading is ended)
|
||||
private createPromise: Promise<void>;
|
||||
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
|
||||
|
@ -187,6 +187,9 @@ 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;
|
||||
|
||||
constructor(private room: Room, MapUrlFile: string, customKey?: string|undefined) {
|
||||
super({
|
||||
|
@ -202,10 +205,11 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
|
||||
this.createPromise = new Promise<void>((resolve, reject): void => {
|
||||
this.createPromiseResolve = resolve;
|
||||
})
|
||||
});
|
||||
this.connectionAnswerPromise = new Promise<RoomJoinedMessageInterface>((resolve, reject): void => {
|
||||
this.connectionAnswerPromiseResolve = resolve;
|
||||
});
|
||||
this.onVisibilityChangeCallback = this.onVisibilityChange.bind(this);
|
||||
}
|
||||
|
||||
//hook preload scene
|
||||
|
@ -495,6 +499,8 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
if (!this.room.isDisconnected()) {
|
||||
this.connect();
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', this.onVisibilityChangeCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -616,6 +622,7 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||
self.chatModeSprite.setVisible(false);
|
||||
self.openChatIcon.setVisible(false);
|
||||
audioManager.restoreVolume();
|
||||
self.onVisibilityChange();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -916,6 +923,8 @@ ${escapedMessage}
|
|||
}
|
||||
|
||||
private onMapExit(exitKey: string) {
|
||||
if (this.mapTransitioning) return;
|
||||
this.mapTransitioning = true;
|
||||
const {roomId, hash} = Room.getIdFromIdentifier(exitKey, this.MapUrlFile, this.instance);
|
||||
if (!roomId) throw new Error('Could not find the room from its exit key: '+exitKey);
|
||||
urlManager.pushStartLayerNameToUrl(hash);
|
||||
|
@ -933,6 +942,7 @@ ${escapedMessage}
|
|||
this.initPositionFromLayerName(hash || defaultStartLayerName);
|
||||
this.CurrentPlayer.x = this.startX;
|
||||
this.CurrentPlayer.y = this.startY;
|
||||
setTimeout(() => this.mapTransitioning = false, 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,6 +968,8 @@ ${escapedMessage}
|
|||
for(const iframeEvents of this.iframeSubscriptionList){
|
||||
iframeEvents.unsubscribe();
|
||||
}
|
||||
|
||||
document.removeEventListener('visibilitychange', this.onVisibilityChangeCallback);
|
||||
}
|
||||
|
||||
private removeAllRemotePlayers(): void {
|
||||
|
@ -1107,6 +1119,7 @@ ${escapedMessage}
|
|||
|
||||
createCollisionWithPlayer() {
|
||||
this.physics.disableUpdate();
|
||||
this.physicsEnabled = false;
|
||||
//add collision layer
|
||||
for (const Layer of this.gameMap.flatLayers) {
|
||||
if (Layer.type == "tilelayer") {
|
||||
|
@ -1251,12 +1264,15 @@ ${escapedMessage}
|
|||
this.CurrentPlayer.moveUser(delta);
|
||||
if (this.CurrentPlayer.isMoving()) {
|
||||
this.dirty = true;
|
||||
this.physics.enableUpdate();
|
||||
} else {
|
||||
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) {
|
||||
this.dirty = true;
|
||||
|
@ -1523,6 +1539,8 @@ ${escapedMessage}
|
|||
mediaManager.addTriggerCloseJitsiFrameButton('close-jisi',() => {
|
||||
this.stopJitsi();
|
||||
});
|
||||
|
||||
this.onVisibilityChange();
|
||||
}
|
||||
|
||||
public stopJitsi(): void {
|
||||
|
@ -1531,6 +1549,7 @@ ${escapedMessage}
|
|||
mediaManager.showGameOverlay();
|
||||
|
||||
mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi');
|
||||
this.onVisibilityChange();
|
||||
}
|
||||
|
||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||
|
@ -1570,4 +1589,20 @@ ${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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {HasMovedEvent} from "./GameManager";
|
||||
import type {HasMovedEvent} from "./GameManager";
|
||||
import {MAX_EXTRAPOLATION_TIME} from "../../Enum/EnvironmentVariable";
|
||||
import {PositionInterface} from "../../Connexion/ConnexionModels";
|
||||
import type {PositionInterface} from "../../Connexion/ConnexionModels";
|
||||
|
||||
export class PlayerMovement {
|
||||
public constructor(private startPosition: PositionInterface, private startTick: number, private endPosition: HasMovedEvent, private endTick: number) {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* This class is in charge of computing the position of all players.
|
||||
* Player movement is delayed by 200ms so position depends on ticks.
|
||||
*/
|
||||
import {PlayerMovement} from "./PlayerMovement";
|
||||
import {HasMovedEvent} from "./GameManager";
|
||||
import type {PlayerMovement} from "./PlayerMovement";
|
||||
import type {HasMovedEvent} from "./GameManager";
|
||||
|
||||
export class PlayersPositionInterpolator {
|
||||
playerMovements: Map<number, PlayerMovement> = new Map<number, PlayerMovement>();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue