Merge branch 'develop' of github.com:thecodingmachine/workadventure into main
This commit is contained in:
@@ -44,7 +44,6 @@ export class TextUtils {
|
||||
options.align = object.text.halign;
|
||||
}
|
||||
|
||||
console.warn(options);
|
||||
const textElem = scene.add.text(object.x, object.y, object.text.text, options);
|
||||
textElem.setAngle(object.rotation);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {ResizableScene} from "../Login/ResizableScene";
|
||||
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";
|
||||
import { SKIP_RENDER_OPTIMIZATIONS } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
/**
|
||||
* A scene that can track its dirty/pristine state.
|
||||
*/
|
||||
export abstract class DirtyScene extends ResizableScene {
|
||||
private isAlreadyTracking: boolean = false;
|
||||
protected dirty:boolean = true;
|
||||
private objectListChanged:boolean = true;
|
||||
protected dirty: boolean = true;
|
||||
private objectListChanged: boolean = true;
|
||||
private physicsEnabled: boolean = false;
|
||||
|
||||
/**
|
||||
@@ -59,7 +59,6 @@ export abstract class DirtyScene extends ResizableScene {
|
||||
this.physicsEnabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private trackAnimation(): void {
|
||||
@@ -71,7 +70,7 @@ export abstract class DirtyScene extends ResizableScene {
|
||||
}
|
||||
|
||||
public markDirty(): void {
|
||||
this.events.once(Phaser.Scenes.Events.POST_UPDATE, () => this.dirty = true);
|
||||
this.events.once(Phaser.Scenes.Events.POST_UPDATE, () => (this.dirty = true));
|
||||
}
|
||||
|
||||
public onResize(): void {
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import {GameScene} from "./GameScene";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import type {Room} from "../../Connexion/Room";
|
||||
import {MenuScene, MenuSceneName} from "../Menu/MenuScene";
|
||||
import {LoginSceneName} from "../Login/LoginScene";
|
||||
import {SelectCharacterSceneName} from "../Login/SelectCharacterScene";
|
||||
import {EnableCameraSceneName} from "../Login/EnableCameraScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import { GameScene } from "./GameScene";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import type { Room } from "../../Connexion/Room";
|
||||
import { MenuScene, MenuSceneName } from "../Menu/MenuScene";
|
||||
import { LoginSceneName } from "../Login/LoginScene";
|
||||
import { SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import { EnableCameraSceneName } from "../Login/EnableCameraScene";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { get } from "svelte/store";
|
||||
import { requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
|
||||
import { helpCameraSettingsVisibleStore } from "../../Stores/HelpCameraSettingsStore";
|
||||
import Axios from "axios";
|
||||
import {get} from "svelte/store";
|
||||
import {requestedCameraState, requestedMicrophoneState} from "../../Stores/MediaStore";
|
||||
import {helpCameraSettingsVisibleStore} from "../../Stores/HelpCameraSettingsStore";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class should be responsible for any scene starting/stopping
|
||||
*/
|
||||
export class GameManager {
|
||||
private playerName: string|null;
|
||||
private characterLayers: string[]|null;
|
||||
private companion: string|null;
|
||||
private startRoom!:Room;
|
||||
currentGameSceneName: string|null = null;
|
||||
private playerName: string | null;
|
||||
private characterLayers: string[] | null;
|
||||
private companion: string | null;
|
||||
private startRoom!: Room;
|
||||
currentGameSceneName: string | null = null;
|
||||
|
||||
constructor() {
|
||||
this.playerName = localUserStore.getName();
|
||||
@@ -57,23 +55,22 @@ export class GameManager {
|
||||
localUserStore.setCharacterLayers(layers);
|
||||
}
|
||||
|
||||
getPlayerName(): string|null {
|
||||
getPlayerName(): string | null {
|
||||
return this.playerName;
|
||||
}
|
||||
|
||||
getCharacterLayers(): string[] {
|
||||
if (!this.characterLayers) {
|
||||
throw 'characterLayers are not set';
|
||||
throw "characterLayers are not set";
|
||||
}
|
||||
return this.characterLayers;
|
||||
}
|
||||
|
||||
|
||||
setCompanion(companion: string|null): void {
|
||||
setCompanion(companion: string | null): void {
|
||||
this.companion = companion;
|
||||
}
|
||||
|
||||
getCompanion(): string|null {
|
||||
getCompanion(): string | null {
|
||||
return this.companion;
|
||||
}
|
||||
|
||||
@@ -82,18 +79,21 @@ export class GameManager {
|
||||
const mapDetail = await room.getMapDetail();
|
||||
|
||||
const gameIndex = scenePlugin.getIndex(roomID);
|
||||
if(gameIndex === -1){
|
||||
const game : Phaser.Scene = new GameScene(room, mapDetail.mapUrl);
|
||||
if (gameIndex === -1) {
|
||||
const game: Phaser.Scene = new GameScene(room, mapDetail.mapUrl);
|
||||
scenePlugin.add(roomID, game, false);
|
||||
}
|
||||
}
|
||||
|
||||
public goToStartingMap(scenePlugin: Phaser.Scenes.ScenePlugin): void {
|
||||
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
|
||||
console.log("starting " + (this.currentGameSceneName || this.startRoom.id));
|
||||
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
|
||||
scenePlugin.launch(MenuSceneName);
|
||||
|
||||
if(!localUserStore.getHelpCameraSettingsShown() && (!get(requestedMicrophoneState) || !get(requestedCameraState))){
|
||||
if (
|
||||
!localUserStore.getHelpCameraSettingsShown() &&
|
||||
(!get(requestedMicrophoneState) || !get(requestedCameraState))
|
||||
) {
|
||||
helpCameraSettingsVisibleStore.set(true);
|
||||
localUserStore.setHelpCameraSettingsShown();
|
||||
}
|
||||
@@ -110,7 +110,7 @@ export class GameManager {
|
||||
* This will close the socket connections and stop the gameScene, but won't remove it.
|
||||
*/
|
||||
leaveGame(scene: Phaser.Scene, targetSceneName: string, sceneClass: Phaser.Scene): void {
|
||||
if (this.currentGameSceneName === null) throw 'No current scene id set!';
|
||||
if (this.currentGameSceneName === null) throw "No current scene id set!";
|
||||
const gameScene: GameScene = scene.scene.get(this.currentGameSceneName) as GameScene;
|
||||
gameScene.cleanupClosingScene();
|
||||
scene.scene.stop(this.currentGameSceneName);
|
||||
@@ -129,13 +129,13 @@ export class GameManager {
|
||||
scene.scene.start(this.currentGameSceneName);
|
||||
scene.scene.wake(MenuSceneName);
|
||||
} else {
|
||||
scene.scene.run(fallbackSceneName)
|
||||
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
|
||||
if (this.currentGameSceneName === null) throw "No current scene id set!";
|
||||
return scene.scene.get(this.currentGameSceneName) as GameScene;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import type {ITiledMap, ITiledMapLayer, ITiledMapLayerProperty} from "../Map/ITiledMap";
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapLayerProperty } from "../Map/ITiledMap";
|
||||
import { flattenGroupLayersMap } from "../Map/LayersFlattener";
|
||||
import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
|
||||
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
|
||||
|
||||
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
|
||||
export type PropertyChangeCallback = (
|
||||
newValue: string | number | boolean | undefined,
|
||||
oldValue: string | number | boolean | undefined,
|
||||
allProps: Map<string, string | boolean | number>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* A wrapper around a ITiledMap interface to provide additional capabilities.
|
||||
@@ -19,37 +23,50 @@ export class GameMap {
|
||||
public readonly flatLayers: ITiledMapLayer[];
|
||||
public readonly phaserLayers: TilemapLayer[] = [];
|
||||
|
||||
public exitUrls: Array<string> = []
|
||||
public exitUrls: Array<string> = [];
|
||||
|
||||
public constructor(private map: ITiledMap, phaserMap: Phaser.Tilemaps.Tilemap, terrains: Array<Phaser.Tilemaps.Tileset>) {
|
||||
public hasStartTile = false;
|
||||
|
||||
public constructor(
|
||||
private map: ITiledMap,
|
||||
phaserMap: Phaser.Tilemaps.Tilemap,
|
||||
terrains: Array<Phaser.Tilemaps.Tileset>
|
||||
) {
|
||||
this.flatLayers = flattenGroupLayersMap(map);
|
||||
let depth = -2;
|
||||
for (const layer of this.flatLayers) {
|
||||
if(layer.type === 'tilelayer'){
|
||||
if (layer.type === "tilelayer") {
|
||||
this.phaserLayers.push(phaserMap.createLayer(layer.name, terrains, 0, 0).setDepth(depth));
|
||||
}
|
||||
if (layer.type === 'objectgroup' && layer.name === 'floorLayer') {
|
||||
if (layer.type === "objectgroup" && layer.name === "floorLayer") {
|
||||
depth = DEPTH_OVERLAY_INDEX;
|
||||
}
|
||||
}
|
||||
for (const tileset of map.tilesets) {
|
||||
tileset?.tiles?.forEach(tile => {
|
||||
tileset?.tiles?.forEach((tile) => {
|
||||
if (tile.properties) {
|
||||
this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties
|
||||
tile.properties.forEach(prop => {
|
||||
if (prop.name == 'name' && typeof prop.value == "string") {
|
||||
this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties;
|
||||
tile.properties.forEach((prop) => {
|
||||
if (prop.name == "name" && typeof prop.value == "string") {
|
||||
this.tileNameMap.set(prop.value, tileset.firstgid + tile.id);
|
||||
}
|
||||
if (prop.name == "exitUrl" && typeof prop.value == "string") {
|
||||
this.exitUrls.push(prop.value);
|
||||
} else if (prop.name == "start") {
|
||||
this.hasStartTile = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public getPropertiesForIndex(index: number): Array<ITiledMapLayerProperty> {
|
||||
if (this.tileSetPropertyMap[index]) {
|
||||
return this.tileSetPropertyMap[index];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the current player (in pixels)
|
||||
@@ -93,7 +110,7 @@ export class GameMap {
|
||||
const properties = new Map<string, string | boolean | number>();
|
||||
|
||||
for (const layer of this.flatLayers) {
|
||||
if (layer.type !== 'tilelayer') {
|
||||
if (layer.type !== "tilelayer") {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -103,7 +120,7 @@ export class GameMap {
|
||||
if (tiles[key] == 0) {
|
||||
continue;
|
||||
}
|
||||
tileIndex = tiles[key]
|
||||
tileIndex = tiles[key];
|
||||
}
|
||||
|
||||
// There is a tile in this layer, let's embed the properties
|
||||
@@ -117,20 +134,20 @@ export class GameMap {
|
||||
}
|
||||
|
||||
if (tileIndex) {
|
||||
this.tileSetPropertyMap[tileIndex]?.forEach(property => {
|
||||
this.tileSetPropertyMap[tileIndex]?.forEach((property) => {
|
||||
if (property.value) {
|
||||
properties.set(property.name, property.value)
|
||||
properties.set(property.name, property.value);
|
||||
} else if (properties.has(property.name)) {
|
||||
properties.delete(property.name)
|
||||
properties.delete(property.name);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
public getMap(): ITiledMap{
|
||||
public getMap(): ITiledMap {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@@ -138,7 +155,12 @@ export class GameMap {
|
||||
return this.tileSetPropertyMap[index] || [];
|
||||
}
|
||||
|
||||
private trigger(propName: string, oldValue: string | number | boolean | undefined, newValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) {
|
||||
private trigger(
|
||||
propName: string,
|
||||
oldValue: string | number | boolean | undefined,
|
||||
newValue: string | number | boolean | undefined,
|
||||
allProps: Map<string, string | boolean | number>
|
||||
) {
|
||||
const callbacksArray = this.callbacks.get(propName);
|
||||
if (callbacksArray !== undefined) {
|
||||
for (const callback of callbacksArray) {
|
||||
@@ -167,7 +189,7 @@ export class GameMap {
|
||||
return this.phaserLayers.find((layer) => layer.layer.name === layerName);
|
||||
}
|
||||
|
||||
public addTerrain(terrain : Phaser.Tilemaps.Tileset): void {
|
||||
public addTerrain(terrain: Phaser.Tilemaps.Tileset): void {
|
||||
for (const phaserLayer of this.phaserLayers) {
|
||||
phaserLayer.tileset.push(terrain);
|
||||
}
|
||||
@@ -175,11 +197,11 @@ export class GameMap {
|
||||
|
||||
private putTileInFlatLayer(index: number, x: number, y: number, layer: string): void {
|
||||
const fLayer = this.findLayer(layer);
|
||||
if ( fLayer == undefined ) {
|
||||
if (fLayer == undefined) {
|
||||
console.error("The layer that you want to change doesn't exist.");
|
||||
return;
|
||||
}
|
||||
if (fLayer.type !== 'tilelayer') {
|
||||
if (fLayer.type !== "tilelayer") {
|
||||
console.error("The layer that you want to change is not a tilelayer. Tile can only be put in tilelayer.");
|
||||
return;
|
||||
}
|
||||
@@ -187,27 +209,25 @@ export class GameMap {
|
||||
console.error("Data of the layer that you want to change is only readable.");
|
||||
return;
|
||||
}
|
||||
fLayer.data[x+y*fLayer.height] = index;
|
||||
fLayer.data[x + y * fLayer.height] = index;
|
||||
}
|
||||
|
||||
public putTile(tile: string | number, x: number, y: number, layer: string): void {
|
||||
const phaserLayer = this.findPhaserLayer(layer);
|
||||
if ( phaserLayer ) {
|
||||
if (phaserLayer) {
|
||||
const tileIndex = this.getIndexForTileType(tile);
|
||||
if ( tileIndex !== undefined ) {
|
||||
if (tileIndex !== undefined) {
|
||||
this.putTileInFlatLayer(tileIndex, x, y, layer);
|
||||
const phaserTile = phaserLayer.putTileAt(tileIndex, x, y);
|
||||
for (const property of this.getTileProperty(tileIndex)) {
|
||||
if ( property.name === "collides" && property.value) {
|
||||
if (property.name === "collides" && property.value) {
|
||||
phaserTile.setCollision(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.error("The tile that you want to place doesn't exist.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.error("The layer that you want to change is not a tilelayer. Tile can only be put in tilelayer.");
|
||||
}
|
||||
}
|
||||
@@ -218,5 +238,4 @@ export class GameMap {
|
||||
}
|
||||
return this.tileNameMap.get(tile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Queue } from "queue-typescript";
|
||||
import type { Subscription } from "rxjs";
|
||||
import { GlobalMessageManager } from "../../Administration/GlobalMessageManager";
|
||||
import { userMessageManager } from "../../Administration/UserMessageManager";
|
||||
@@ -14,20 +13,9 @@ import type {
|
||||
PositionInterface,
|
||||
RoomJoinedMessageInterface,
|
||||
} from "../../Connexion/ConnexionModels";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { Room } from "../../Connexion/Room";
|
||||
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||
import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
||||
import { DEBUG_MODE, JITSI_PRIVATE_MODE, MAX_PER_GROUP, POSITION_DELAY } from "../../Enum/EnvironmentVariable";
|
||||
import { TextureError } from "../../Exception/TextureError";
|
||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
||||
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
||||
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||
import { urlManager } from "../../Url/UrlManager";
|
||||
import { audioManager } from "../../WebRtc/AudioManager";
|
||||
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import { jitsiFactory } from "../../WebRtc/JitsiFactory";
|
||||
|
||||
import { Queue } from "queue-typescript";
|
||||
import {
|
||||
AUDIO_LOOP_PROPERTY,
|
||||
AUDIO_VOLUME_PROPERTY,
|
||||
@@ -39,15 +27,21 @@ import {
|
||||
TRIGGER_WEBSITE_PROPERTIES,
|
||||
WEBSITE_MESSAGE_PROPERTIES,
|
||||
} from "../../WebRtc/LayoutManager";
|
||||
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
||||
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
||||
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||
import { Room } from "../../Connexion/Room";
|
||||
import { jitsiFactory } from "../../WebRtc/JitsiFactory";
|
||||
import { urlManager } from "../../Url/UrlManager";
|
||||
import { audioManager } from "../../WebRtc/AudioManager";
|
||||
import { TextureError } from "../../Exception/TextureError";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import { mediaManager } from "../../WebRtc/MediaManager";
|
||||
import { SimplePeer, UserSimplePeerInterface } from "../../WebRtc/SimplePeer";
|
||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import { ChatModeIcon } from "../Components/ChatModeIcon";
|
||||
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
||||
import { addLoader } from "../Components/Loader";
|
||||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||
import { OpenChatIcon, openChatIconName } from "../Components/OpenChatIcon";
|
||||
import { PresentationModeIcon } from "../Components/PresentationModeIcon";
|
||||
import { TextUtils } from "../Components/TextUtils";
|
||||
import { lazyLoadPlayerCharacterTextures, loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager";
|
||||
import { RemotePlayer } from "../Entity/RemotePlayer";
|
||||
import type { ActionableItem } from "../Items/ActionableItem";
|
||||
@@ -58,7 +52,6 @@ import type {
|
||||
ITiledMapLayer,
|
||||
ITiledMapLayerProperty,
|
||||
ITiledMapObject,
|
||||
ITiledMapTileLayer,
|
||||
ITiledTileSet,
|
||||
} from "../Map/ITiledMap";
|
||||
import { MenuScene, MenuSceneName } from "../Menu/MenuScene";
|
||||
@@ -66,13 +59,8 @@ import { PlayerAnimationDirections } from "../Player/Animation";
|
||||
import { hasMovedEventName, Player, requestEmoteEventName } from "../Player/Player";
|
||||
import { ErrorSceneName } from "../Reconnecting/ErrorScene";
|
||||
import { ReconnectingSceneName } from "../Reconnecting/ReconnectingScene";
|
||||
import { waScaleManager } from "../Services/WaScaleManager";
|
||||
import { PinchManager } from "../UserInput/PinchManager";
|
||||
import { UserInputManager } from "../UserInput/UserInputManager";
|
||||
import type { AddPlayerInterface } from "./AddPlayerInterface";
|
||||
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
|
||||
import { DirtyScene } from "./DirtyScene";
|
||||
import { EmoteManager } from "./EmoteManager";
|
||||
import { gameManager } from "./GameManager";
|
||||
import { GameMap } from "./GameMap";
|
||||
import { PlayerMovement } from "./PlayerMovement";
|
||||
@@ -83,12 +71,22 @@ 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 { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import { DirtyScene } from "./DirtyScene";
|
||||
import { TextUtils } from "../Components/TextUtils";
|
||||
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||
import { PinchManager } from "../UserInput/PinchManager";
|
||||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||
import { waScaleManager } from "../Services/WaScaleManager";
|
||||
import { EmoteManager } from "./EmoteManager";
|
||||
import EVENT_TYPE = Phaser.Scenes.Events;
|
||||
import RenderTexture = Phaser.GameObjects.RenderTexture;
|
||||
import Tilemap = Phaser.Tilemaps.Tilemap;
|
||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||
|
||||
import AnimatedTiles from "phaser-animated-tiles";
|
||||
import { StartPositionCalculator } from "./StartPositionCalculator";
|
||||
import { soundManager } from "./SoundManager";
|
||||
import { peerStore, screenSharingPeerStore } from "../../Stores/PeerStore";
|
||||
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
||||
@@ -129,8 +127,6 @@ interface DeleteGroupEventInterface {
|
||||
groupId: number;
|
||||
}
|
||||
|
||||
const defaultStartLayerName = "start";
|
||||
|
||||
export class GameScene extends DirtyScene {
|
||||
Terrains: Array<Phaser.Tilemaps.Tileset>;
|
||||
CurrentPlayer!: Player;
|
||||
@@ -141,8 +137,6 @@ export class GameScene extends DirtyScene {
|
||||
mapFile!: ITiledMap;
|
||||
animatedTiles!: AnimatedTiles;
|
||||
groups: Map<number, Sprite>;
|
||||
startX!: number;
|
||||
startY!: number;
|
||||
circleTexture!: CanvasTexture;
|
||||
circleRedTexture!: CanvasTexture;
|
||||
pendingEvents: Queue<
|
||||
@@ -194,7 +188,6 @@ export class GameScene extends DirtyScene {
|
||||
private outlinedItem: ActionableItem | null = null;
|
||||
public userInputManager!: UserInputManager;
|
||||
private isReconnecting: boolean | undefined = undefined;
|
||||
private startLayerName!: string | null;
|
||||
private openChatIcon!: OpenChatIcon;
|
||||
private playerName!: string;
|
||||
private characterLayers!: string[];
|
||||
@@ -206,6 +199,7 @@ export class GameScene extends DirtyScene {
|
||||
private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time.
|
||||
private emoteManager!: EmoteManager;
|
||||
private preloading: boolean = true;
|
||||
startPositionCalculator!: StartPositionCalculator;
|
||||
|
||||
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
||||
super({
|
||||
@@ -426,7 +420,6 @@ export class GameScene extends DirtyScene {
|
||||
|
||||
gameManager.gameSceneIsCreated(this);
|
||||
urlManager.pushRoomIdToUrl(this.room);
|
||||
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
this.pinchManager = new PinchManager(this);
|
||||
@@ -489,7 +482,12 @@ export class GameScene extends DirtyScene {
|
||||
this.loadNextGame(exitUrl);
|
||||
});
|
||||
|
||||
this.initStartXAndStartY();
|
||||
this.startPositionCalculator = new StartPositionCalculator(
|
||||
this.gameMap,
|
||||
this.mapFile,
|
||||
this.initPosition,
|
||||
urlManager.getStartLayerNameFromUrl()
|
||||
);
|
||||
|
||||
//add entities
|
||||
this.Objects = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
@@ -586,8 +584,7 @@ export class GameScene extends DirtyScene {
|
||||
this.playerName,
|
||||
this.characterLayers,
|
||||
{
|
||||
x: this.startX,
|
||||
y: this.startY,
|
||||
...this.startPositionCalculator.startPosition,
|
||||
},
|
||||
{
|
||||
left: camera.scrollX,
|
||||
@@ -995,8 +992,8 @@ export class GameScene extends DirtyScene {
|
||||
})
|
||||
);
|
||||
|
||||
this.iframeSubscriptionList.push(
|
||||
iframeListener.enablePlayerControlStream.subscribe(()=>{
|
||||
this.iframeSubscriptionList.push(
|
||||
iframeListener.enablePlayerControlStream.subscribe(() => {
|
||||
this.userInputManager.restoreControls();
|
||||
})
|
||||
);
|
||||
@@ -1053,16 +1050,21 @@ export class GameScene extends DirtyScene {
|
||||
})
|
||||
);
|
||||
|
||||
iframeListener.registerAnswerer('getState', () => {
|
||||
return {
|
||||
mapUrl: this.MapUrlFile,
|
||||
startLayerName: this.startPositionCalculator.startLayerName,
|
||||
uuid: localUserStore.getLocalUser()?.uuid,
|
||||
nickname: localUserStore.getName(),
|
||||
roomId: this.RoomId,
|
||||
tags: this.connection ? this.connection.getAllTags() : [],
|
||||
};
|
||||
});
|
||||
this.iframeSubscriptionList.push(
|
||||
iframeListener.gameStateStream.subscribe(() => {
|
||||
iframeListener.sendGameStateEvent({
|
||||
mapUrl: this.MapUrlFile,
|
||||
startLayerName: this.startLayerName,
|
||||
uuid: localUserStore.getLocalUser()?.uuid,
|
||||
nickname: localUserStore.getName(),
|
||||
roomId: this.RoomId,
|
||||
tags: this.connection ? this.connection.getAllTags() : [],
|
||||
});
|
||||
iframeListener.setTilesStream.subscribe((eventTiles) => {
|
||||
for (const eventTile of eventTiles) {
|
||||
this.gameMap.putTile(eventTile.tile, eventTile.x, eventTile.y, eventTile.layer);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1104,11 +1106,11 @@ export class GameScene extends DirtyScene {
|
||||
console.warn('Could not find layer "' + layerName + '" when calling setProperty');
|
||||
return;
|
||||
}
|
||||
const property = (layer.properties as ITiledMapLayerProperty[])?.find(
|
||||
(property) => property.name === propertyName
|
||||
);
|
||||
if (property === undefined) {
|
||||
if (layer.properties === undefined) {
|
||||
layer.properties = [];
|
||||
}
|
||||
const property = layer.properties.find((property) => property.name === propertyName);
|
||||
if (property === undefined) {
|
||||
layer.properties.push({ name: propertyName, type: typeof propertyValue, value: propertyValue });
|
||||
return;
|
||||
}
|
||||
@@ -1134,7 +1136,9 @@ export class GameScene extends DirtyScene {
|
||||
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);
|
||||
if (hash) {
|
||||
urlManager.pushStartLayerNameToUrl(hash);
|
||||
}
|
||||
const menuScene: MenuScene = this.scene.get(MenuSceneName) as MenuScene;
|
||||
menuScene.reset();
|
||||
if (roomId !== this.scene.key) {
|
||||
@@ -1148,9 +1152,9 @@ export class GameScene extends DirtyScene {
|
||||
this.scene.start(roomId);
|
||||
} else {
|
||||
//if the exit points to the current map, we simply teleport the user back to the startLayer
|
||||
this.initPositionFromLayerName(hash || defaultStartLayerName);
|
||||
this.CurrentPlayer.x = this.startX;
|
||||
this.CurrentPlayer.y = this.startY;
|
||||
this.startPositionCalculator.initPositionFromLayerName(hash, hash);
|
||||
this.CurrentPlayer.x = this.startPositionCalculator.startPosition.x;
|
||||
this.CurrentPlayer.y = this.startPositionCalculator.startPosition.y;
|
||||
setTimeout(() => (this.mapTransitioning = false), 500);
|
||||
}
|
||||
}
|
||||
@@ -1176,6 +1180,7 @@ export class GameScene extends DirtyScene {
|
||||
this.emoteManager.destroy();
|
||||
this.peerStoreUnsubscribe();
|
||||
this.biggestAvailableAreaStoreUnsubscribe();
|
||||
iframeListener.unregisterAnswerer('getState');
|
||||
|
||||
mediaManager.hideGameOverlay();
|
||||
|
||||
@@ -1197,46 +1202,6 @@ export class GameScene extends DirtyScene {
|
||||
this.MapPlayersByKey = new Map<number, RemotePlayer>();
|
||||
}
|
||||
|
||||
private initStartXAndStartY() {
|
||||
// If there is an init position passed
|
||||
if (this.initPosition !== null) {
|
||||
this.startX = this.initPosition.x;
|
||||
this.startY = this.initPosition.y;
|
||||
} else {
|
||||
// Now, let's find the start layer
|
||||
if (this.startLayerName) {
|
||||
this.initPositionFromLayerName(this.startLayerName);
|
||||
}
|
||||
if (this.startX === undefined) {
|
||||
// If we have no start layer specified or if the hash passed does not exist, let's go with the default start position.
|
||||
this.initPositionFromLayerName(defaultStartLayerName);
|
||||
}
|
||||
}
|
||||
// Still no start position? Something is wrong with the map, we need a "start" layer.
|
||||
if (this.startX === undefined) {
|
||||
console.warn(
|
||||
'This map is missing a layer named "start" that contains the available default start positions.'
|
||||
);
|
||||
// Let's start in the middle of the map
|
||||
this.startX = this.mapFile.width * 16;
|
||||
this.startY = this.mapFile.height * 16;
|
||||
}
|
||||
}
|
||||
|
||||
private initPositionFromLayerName(layerName: string) {
|
||||
for (const layer of this.gameMap.flatLayers) {
|
||||
if (
|
||||
(layerName === layer.name || layer.name.endsWith("/" + layerName)) &&
|
||||
layer.type === "tilelayer" &&
|
||||
(layerName === defaultStartLayerName || this.isStartLayer(layer))
|
||||
) {
|
||||
const startPosition = this.startUser(layer);
|
||||
this.startX = startPosition.x + this.mapFile.tilewidth / 2;
|
||||
this.startY = startPosition.y + this.mapFile.tileheight / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getExitUrl(layer: ITiledMapLayer): string | undefined {
|
||||
return this.getProperty(layer, "exitUrl") as string | undefined;
|
||||
}
|
||||
@@ -1248,10 +1213,6 @@ export class GameScene extends DirtyScene {
|
||||
return this.getProperty(layer, "exitSceneUrl") as string | undefined;
|
||||
}
|
||||
|
||||
private isStartLayer(layer: ITiledMapLayer): boolean {
|
||||
return this.getProperty(layer, "startLayer") == true;
|
||||
}
|
||||
|
||||
private getScriptUrls(map: ITiledMap): string[] {
|
||||
return (this.getProperties(map, "script") as string[]).map((script) =>
|
||||
new URL(script, this.MapUrlFile).toString()
|
||||
@@ -1289,33 +1250,6 @@ export class GameScene extends DirtyScene {
|
||||
return gameManager.loadMap(room, this.scene).catch(() => {});
|
||||
}
|
||||
|
||||
private startUser(layer: ITiledMapTileLayer): PositionInterface {
|
||||
const tiles = layer.data;
|
||||
if (typeof tiles === "string") {
|
||||
throw new Error("The content of a JSON map must be filled as a JSON array, not as a string");
|
||||
}
|
||||
const possibleStartPositions: PositionInterface[] = [];
|
||||
tiles.forEach((objectKey: number, key: number) => {
|
||||
if (objectKey === 0) {
|
||||
return;
|
||||
}
|
||||
const y = Math.floor(key / layer.width);
|
||||
const x = key % layer.width;
|
||||
|
||||
possibleStartPositions.push({ x: x * this.mapFile.tilewidth, y: y * this.mapFile.tilewidth });
|
||||
});
|
||||
// Get a value at random amongst allowed values
|
||||
if (possibleStartPositions.length === 0) {
|
||||
console.warn('The start layer "' + layer.name + '" for this map is empty.');
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
// Choose one of the available start positions at random amongst the list of available start positions.
|
||||
return possibleStartPositions[Math.floor(Math.random() * possibleStartPositions.length)];
|
||||
}
|
||||
|
||||
//todo: in a dedicated class/function?
|
||||
initCamera() {
|
||||
this.cameras.main.setBounds(0, 0, this.Map.widthInPixels, this.Map.heightInPixels);
|
||||
@@ -1348,8 +1282,8 @@ export class GameScene extends DirtyScene {
|
||||
try {
|
||||
this.CurrentPlayer = new Player(
|
||||
this,
|
||||
this.startX,
|
||||
this.startY,
|
||||
this.startPositionCalculator.startPosition.x,
|
||||
this.startPositionCalculator.startPosition.y,
|
||||
this.playerName,
|
||||
texturesPromise,
|
||||
PlayerAnimationDirections.Down,
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { MAX_EXTRAPOLATION_TIME } from "../../Enum/EnvironmentVariable";
|
||||
import type { PositionInterface } from "../../Connexion/ConnexionModels";
|
||||
import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
|
||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||
|
||||
export class PlayerMovement {
|
||||
public constructor(private startPosition: PositionInterface, private startTick: number, private endPosition: HasPlayerMovedEvent, private endTick: number) {
|
||||
}
|
||||
public constructor(
|
||||
private startPosition: PositionInterface,
|
||||
private startTick: number,
|
||||
private endPosition: HasPlayerMovedEvent,
|
||||
private endTick: number
|
||||
) {}
|
||||
|
||||
public isOutdated(tick: number): boolean {
|
||||
//console.log(tick, this.endTick, MAX_EXTRAPOLATION_TIME)
|
||||
@@ -24,14 +28,18 @@ export class PlayerMovement {
|
||||
return this.endPosition;
|
||||
}
|
||||
|
||||
const x = (this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.x;
|
||||
const y = (this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.y;
|
||||
const x =
|
||||
(this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) +
|
||||
this.startPosition.x;
|
||||
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,
|
||||
direction: this.endPosition.direction,
|
||||
moving: true
|
||||
}
|
||||
moving: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This class is in charge of computing the position of all players.
|
||||
* Player movement is delayed by 200ms so position depends on ticks.
|
||||
*/
|
||||
import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
|
||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||
import type { PlayerMovement } from "./PlayerMovement";
|
||||
|
||||
export class PlayersPositionInterpolator {
|
||||
@@ -24,7 +24,7 @@ export class PlayersPositionInterpolator {
|
||||
this.playerMovements.delete(userId);
|
||||
}
|
||||
//console.log("moving")
|
||||
positions.set(userId, playerMovement.getPosition(tick))
|
||||
positions.set(userId, playerMovement.getPosition(tick));
|
||||
});
|
||||
return positions;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import type { PositionInterface } from "../../Connexion/ConnexionModels";
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapTileLayer } from "../Map/ITiledMap";
|
||||
import type { GameMap } from "./GameMap";
|
||||
|
||||
const defaultStartLayerName = "start";
|
||||
|
||||
export class StartPositionCalculator {
|
||||
public startPosition!: PositionInterface;
|
||||
|
||||
constructor(
|
||||
private readonly gameMap: GameMap,
|
||||
private readonly mapFile: ITiledMap,
|
||||
private readonly initPosition: PositionInterface | null,
|
||||
public readonly startLayerName: string | null
|
||||
) {
|
||||
this.initStartXAndStartY();
|
||||
}
|
||||
private initStartXAndStartY() {
|
||||
// If there is an init position passed
|
||||
if (this.initPosition !== null) {
|
||||
this.startPosition = this.initPosition;
|
||||
} else {
|
||||
// Now, let's find the start layer
|
||||
if (this.startLayerName) {
|
||||
this.initPositionFromLayerName(this.startLayerName, this.startLayerName);
|
||||
}
|
||||
if (this.startPosition === undefined) {
|
||||
// If we have no start layer specified or if the hash passed does not exist, let's go with the default start position.
|
||||
this.initPositionFromLayerName(defaultStartLayerName, this.startLayerName);
|
||||
}
|
||||
}
|
||||
// Still no start position? Something is wrong with the map, we need a "start" layer.
|
||||
if (this.startPosition === undefined) {
|
||||
console.warn(
|
||||
'This map is missing a layer named "start" that contains the available default start positions.'
|
||||
);
|
||||
// Let's start in the middle of the map
|
||||
this.startPosition = {
|
||||
x: this.mapFile.width * 16,
|
||||
y: this.mapFile.height * 16,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param selectedLayer this is always the layer that is selected with the hash in the url
|
||||
* @param selectedOrDefaultLayer this can also be the {defaultStartLayerName} if the {selectedLayer} didnt yield any start points
|
||||
*/
|
||||
public initPositionFromLayerName(selectedOrDefaultLayer: string | null, selectedLayer: string | null) {
|
||||
if (!selectedOrDefaultLayer) {
|
||||
selectedOrDefaultLayer = defaultStartLayerName;
|
||||
}
|
||||
for (const layer of this.gameMap.flatLayers) {
|
||||
if (
|
||||
(selectedOrDefaultLayer === layer.name || layer.name.endsWith("/" + selectedOrDefaultLayer)) &&
|
||||
layer.type === "tilelayer" &&
|
||||
(selectedOrDefaultLayer === defaultStartLayerName || this.isStartLayer(layer))
|
||||
) {
|
||||
const startPosition = this.startUser(layer, selectedLayer);
|
||||
this.startPosition = {
|
||||
x: startPosition.x + this.mapFile.tilewidth / 2,
|
||||
y: startPosition.y + this.mapFile.tileheight / 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isStartLayer(layer: ITiledMapLayer): boolean {
|
||||
return this.getProperty(layer, "startLayer") == true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param selectedLayer this is always the layer that is selected with the hash in the url
|
||||
* @param selectedOrDefaultLayer this can also be the default layer if the {selectedLayer} didnt yield any start points
|
||||
*/
|
||||
private startUser(selectedOrDefaultLayer: ITiledMapTileLayer, selectedLayer: string | null): PositionInterface {
|
||||
const tiles = selectedOrDefaultLayer.data;
|
||||
if (typeof tiles === "string") {
|
||||
throw new Error("The content of a JSON map must be filled as a JSON array, not as a string");
|
||||
}
|
||||
const possibleStartPositions: PositionInterface[] = [];
|
||||
tiles.forEach((objectKey: number, key: number) => {
|
||||
if (objectKey === 0) {
|
||||
return;
|
||||
}
|
||||
const y = Math.floor(key / selectedOrDefaultLayer.width);
|
||||
const x = key % selectedOrDefaultLayer.width;
|
||||
|
||||
if (selectedLayer && this.gameMap.hasStartTile) {
|
||||
const properties = this.gameMap.getPropertiesForIndex(objectKey);
|
||||
if (
|
||||
!properties.length ||
|
||||
!properties.some((property) => property.name == "start" && property.value == selectedLayer)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
possibleStartPositions.push({ x: x * this.mapFile.tilewidth, y: y * this.mapFile.tilewidth });
|
||||
});
|
||||
// Get a value at random amongst allowed values
|
||||
if (possibleStartPositions.length === 0) {
|
||||
console.warn('The start layer "' + selectedOrDefaultLayer.name + '" for this map is empty.');
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
// Choose one of the available start positions at random amongst the list of available start positions.
|
||||
return possibleStartPositions[Math.floor(Math.random() * possibleStartPositions.length)];
|
||||
}
|
||||
|
||||
private getProperty(layer: ITiledMapLayer | ITiledMap, name: string): string | boolean | number | undefined {
|
||||
const properties: ITiledMapLayerProperty[] | undefined = layer.properties;
|
||||
if (!properties) {
|
||||
return undefined;
|
||||
}
|
||||
const obj = properties.find(
|
||||
(property: ITiledMapLayerProperty) => property.name.toLowerCase() === name.toLowerCase()
|
||||
);
|
||||
if (obj === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return obj.value;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ export interface ITiledMap {
|
||||
export interface ITiledMapLayerProperty {
|
||||
name: string;
|
||||
type: string;
|
||||
value: string|boolean|number|undefined;
|
||||
value: string | boolean | number | undefined;
|
||||
}
|
||||
|
||||
/*export interface ITiledMapLayerBooleanProperty {
|
||||
@@ -48,7 +48,7 @@ export interface ITiledMapLayerProperty {
|
||||
export type ITiledMapLayer = ITiledMapGroupLayer | ITiledMapObjectLayer | ITiledMapTileLayer;
|
||||
|
||||
export interface ITiledMapGroupLayer {
|
||||
id?: number,
|
||||
id?: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
@@ -64,8 +64,8 @@ export interface ITiledMapGroupLayer {
|
||||
}
|
||||
|
||||
export interface ITiledMapTileLayer {
|
||||
id?: number,
|
||||
data: number[]|string;
|
||||
id?: number;
|
||||
data: number[] | string;
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
@@ -87,7 +87,7 @@ export interface ITiledMapTileLayer {
|
||||
}
|
||||
|
||||
export interface ITiledMapObjectLayer {
|
||||
id?: number,
|
||||
id?: number;
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
@@ -117,7 +117,7 @@ export interface ITiledMapObject {
|
||||
gid: number;
|
||||
height: number;
|
||||
name: string;
|
||||
properties: {[key: string]: string};
|
||||
properties: { [key: string]: string };
|
||||
rotation: number;
|
||||
type: string;
|
||||
visible: boolean;
|
||||
@@ -133,26 +133,26 @@ export interface ITiledMapObject {
|
||||
/**
|
||||
* Polygon points
|
||||
*/
|
||||
polygon: {x: number, y: number}[];
|
||||
polygon: { x: number; y: number }[];
|
||||
|
||||
/**
|
||||
* Polyline points
|
||||
*/
|
||||
polyline: {x: number, y: number}[];
|
||||
polyline: { x: number; y: number }[];
|
||||
|
||||
text?: ITiledText
|
||||
text?: ITiledText;
|
||||
}
|
||||
|
||||
export interface ITiledText {
|
||||
text: string,
|
||||
wrap?: boolean,
|
||||
fontfamily?: string,
|
||||
pixelsize?: number,
|
||||
color?: string,
|
||||
underline?: boolean,
|
||||
italic?: boolean,
|
||||
strikeout?: boolean,
|
||||
halign?: "center"|"right"|"justify"|"left"
|
||||
text: string;
|
||||
wrap?: boolean;
|
||||
fontfamily?: string;
|
||||
pixelsize?: number;
|
||||
color?: string;
|
||||
underline?: boolean;
|
||||
italic?: boolean;
|
||||
strikeout?: boolean;
|
||||
halign?: "center" | "right" | "justify" | "left";
|
||||
}
|
||||
|
||||
export interface ITiledTileSet {
|
||||
@@ -163,7 +163,7 @@ export interface ITiledTileSet {
|
||||
imagewidth: number;
|
||||
margin: number;
|
||||
name: string;
|
||||
properties: {[key: string]: string};
|
||||
properties: { [key: string]: string };
|
||||
spacing: number;
|
||||
tilecount: number;
|
||||
tileheight: number;
|
||||
@@ -179,10 +179,10 @@ export interface ITiledTileSet {
|
||||
}
|
||||
|
||||
export interface ITile {
|
||||
id: number,
|
||||
type?: string
|
||||
id: number;
|
||||
type?: string;
|
||||
|
||||
properties?: Array<ITiledMapLayerProperty>
|
||||
properties?: Array<ITiledMapLayerProperty>;
|
||||
}
|
||||
|
||||
export interface ITiledMapTerrain {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import type {ITiledMap, ITiledMapLayer} from "./ITiledMap";
|
||||
import type { ITiledMap, ITiledMapLayer } from "./ITiledMap";
|
||||
|
||||
/**
|
||||
* Flatten the grouped layers
|
||||
*/
|
||||
export function flattenGroupLayersMap(map: ITiledMap) {
|
||||
const flatLayers: ITiledMapLayer[] = [];
|
||||
flattenGroupLayers(map.layers, '', flatLayers);
|
||||
flattenGroupLayers(map.layers, "", flatLayers);
|
||||
return flatLayers;
|
||||
}
|
||||
|
||||
function flattenGroupLayers(layers : ITiledMapLayer[], prefix : string, flatLayers: ITiledMapLayer[]) {
|
||||
function flattenGroupLayers(layers: ITiledMapLayer[], prefix: string, flatLayers: ITiledMapLayer[]) {
|
||||
for (const layer of layers) {
|
||||
if (layer.type === 'group') {
|
||||
flattenGroupLayers(layer.layers, prefix + layer.name + '/', flatLayers);
|
||||
if (layer.type === "group") {
|
||||
flattenGroupLayers(layer.layers, prefix + layer.name + "/", flatLayers);
|
||||
} else {
|
||||
layer.name = prefix+layer.name
|
||||
layer.name = prefix + layer.name;
|
||||
flatLayers.push(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+113
-105
@@ -1,29 +1,29 @@
|
||||
import {LoginScene, LoginSceneName} from "../Login/LoginScene";
|
||||
import {SelectCharacterScene, SelectCharacterSceneName} from "../Login/SelectCharacterScene";
|
||||
import {SelectCompanionScene, SelectCompanionSceneName} from "../Login/SelectCompanionScene";
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {gameReportKey, gameReportRessource, ReportMenu} from "./ReportMenu";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {GameConnexionTypes} from "../../Url/UrlManager";
|
||||
import {WarningContainer, warningContainerHtml, warningContainerKey} from "../Components/WarningContainer";
|
||||
import {worldFullWarningStream} from "../../Connexion/WorldFullWarningStream";
|
||||
import {menuIconVisible} from "../../Stores/MenuStore";
|
||||
import {videoConstraintStore} from "../../Stores/MediaStore";
|
||||
import {showReportScreenStore} from "../../Stores/ShowReportScreenStore";
|
||||
import { HtmlUtils } from '../../WebRtc/HtmlUtils';
|
||||
import { iframeListener } from '../../Api/IframeListener';
|
||||
import { Subscription } from 'rxjs';
|
||||
import {registerMenuCommandStream} from "../../Api/Events/ui/MenuItemRegisterEvent";
|
||||
import {sendMenuClickedEvent} from "../../Api/iframe/Ui/MenuItem";
|
||||
import {consoleGlobalMessageManagerVisibleStore} from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import {get} from "svelte/store";
|
||||
import { LoginScene, LoginSceneName } from "../Login/LoginScene";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import { SelectCompanionScene, SelectCompanionSceneName } from "../Login/SelectCompanionScene";
|
||||
import { gameManager } from "../Game/GameManager";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { gameReportKey, gameReportRessource, ReportMenu } from "./ReportMenu";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import { GameConnexionTypes } from "../../Url/UrlManager";
|
||||
import { WarningContainer, warningContainerHtml, warningContainerKey } from "../Components/WarningContainer";
|
||||
import { worldFullWarningStream } from "../../Connexion/WorldFullWarningStream";
|
||||
import { menuIconVisible } from "../../Stores/MenuStore";
|
||||
import { videoConstraintStore } from "../../Stores/MediaStore";
|
||||
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import { iframeListener } from "../../Api/IframeListener";
|
||||
import { Subscription } from "rxjs";
|
||||
import { registerMenuCommandStream } from "../../Api/Events/ui/MenuItemRegisterEvent";
|
||||
import { sendMenuClickedEvent } from "../../Api/iframe/Ui/MenuItem";
|
||||
import { consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
export const MenuSceneName = 'MenuScene';
|
||||
const gameMenuKey = 'gameMenu';
|
||||
const gameMenuIconKey = 'gameMenuIcon';
|
||||
const gameSettingsMenuKey = 'gameSettingsMenu';
|
||||
const gameShare = 'gameShare';
|
||||
export const MenuSceneName = "MenuScene";
|
||||
const gameMenuKey = "gameMenu";
|
||||
const gameMenuIconKey = "gameMenuIcon";
|
||||
const gameSettingsMenuKey = "gameSettingsMenu";
|
||||
const gameShare = "gameShare";
|
||||
|
||||
const closedSideMenuX = -1000;
|
||||
const openedSideMenuX = 0;
|
||||
@@ -44,45 +44,49 @@ export class MenuScene extends Phaser.Scene {
|
||||
private menuButton!: Phaser.GameObjects.DOMElement;
|
||||
private warningContainer: WarningContainer | null = null;
|
||||
private warningContainerTimeout: NodeJS.Timeout | null = null;
|
||||
private subscriptions = new Subscription()
|
||||
private subscriptions = new Subscription();
|
||||
constructor() {
|
||||
super({ key: MenuSceneName });
|
||||
|
||||
this.gameQualityValue = localUserStore.getGameQualityValue();
|
||||
this.videoQualityValue = localUserStore.getVideoQualityValue();
|
||||
|
||||
this.subscriptions.add(registerMenuCommandStream.subscribe(menuCommand => {
|
||||
this.addMenuOption(menuCommand);
|
||||
}))
|
||||
this.subscriptions.add(
|
||||
registerMenuCommandStream.subscribe((menuCommand) => {
|
||||
this.addMenuOption(menuCommand);
|
||||
})
|
||||
);
|
||||
|
||||
this.subscriptions.add(iframeListener.unregisterMenuCommandStream.subscribe(menuCommand => {
|
||||
this.destroyMenu(menuCommand);
|
||||
}))
|
||||
this.subscriptions.add(
|
||||
iframeListener.unregisterMenuCommandStream.subscribe((menuCommand) => {
|
||||
this.destroyMenu(menuCommand);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
reset() {
|
||||
const addedMenuItems = [...this.menuElement.node.querySelectorAll(".fromApi")];
|
||||
for (let index = addedMenuItems.length - 1; index >= 0; index--) {
|
||||
addedMenuItems[index].remove()
|
||||
addedMenuItems[index].remove();
|
||||
}
|
||||
}
|
||||
|
||||
public addMenuOption(menuText: string) {
|
||||
const wrappingSection = document.createElement("section")
|
||||
const wrappingSection = document.createElement("section");
|
||||
const escapedHtml = HtmlUtils.escapeHtml(menuText);
|
||||
wrappingSection.innerHTML = `<button class="fromApi" id="${escapedHtml}">${escapedHtml}</button>`
|
||||
wrappingSection.innerHTML = `<button class="fromApi" id="${escapedHtml}">${escapedHtml}</button>`;
|
||||
const menuItemContainer = this.menuElement.node.querySelector("#gameMenu main");
|
||||
if (menuItemContainer) {
|
||||
menuItemContainer.querySelector(`#${escapedHtml}.fromApi`)?.remove()
|
||||
menuItemContainer.insertBefore(wrappingSection, menuItemContainer.querySelector("#socialLinks"))
|
||||
menuItemContainer.querySelector(`#${escapedHtml}.fromApi`)?.remove();
|
||||
menuItemContainer.insertBefore(wrappingSection, menuItemContainer.querySelector("#socialLinks"));
|
||||
}
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.html(gameMenuKey, 'resources/html/gameMenu.html');
|
||||
this.load.html(gameMenuIconKey, 'resources/html/gameMenuIcon.html');
|
||||
this.load.html(gameSettingsMenuKey, 'resources/html/gameQualityMenu.html');
|
||||
this.load.html(gameShare, 'resources/html/gameShare.html');
|
||||
this.load.html(gameMenuKey, "resources/html/gameMenu.html");
|
||||
this.load.html(gameMenuIconKey, "resources/html/gameMenuIcon.html");
|
||||
this.load.html(gameSettingsMenuKey, "resources/html/gameQualityMenu.html");
|
||||
this.load.html(gameShare, "resources/html/gameShare.html");
|
||||
this.load.html(gameReportKey, gameReportRessource);
|
||||
this.load.html(warningContainerKey, warningContainerHtml);
|
||||
}
|
||||
@@ -91,26 +95,28 @@ export class MenuScene extends Phaser.Scene {
|
||||
menuIconVisible.set(true);
|
||||
this.menuElement = this.add.dom(closedSideMenuX, 30).createFromCache(gameMenuKey);
|
||||
this.menuElement.setOrigin(0);
|
||||
MenuScene.revealMenusAfterInit(this.menuElement, 'gameMenu');
|
||||
MenuScene.revealMenusAfterInit(this.menuElement, "gameMenu");
|
||||
|
||||
const middleX = (window.innerWidth / 3) - 298;
|
||||
const middleX = window.innerWidth / 3 - 298;
|
||||
this.gameQualityMenuElement = this.add.dom(middleX, -400).createFromCache(gameSettingsMenuKey);
|
||||
MenuScene.revealMenusAfterInit(this.gameQualityMenuElement, 'gameQuality');
|
||||
|
||||
MenuScene.revealMenusAfterInit(this.gameQualityMenuElement, "gameQuality");
|
||||
|
||||
this.gameShareElement = this.add.dom(middleX, -400).createFromCache(gameShare);
|
||||
MenuScene.revealMenusAfterInit(this.gameShareElement, gameShare);
|
||||
this.gameShareElement.addListener('click');
|
||||
this.gameShareElement.on('click', (event: MouseEvent) => {
|
||||
this.gameShareElement.addListener("click");
|
||||
this.gameShareElement.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if ((event?.target as HTMLInputElement).id === 'gameShareFormSubmit') {
|
||||
if ((event?.target as HTMLInputElement).id === "gameShareFormSubmit") {
|
||||
this.copyLink();
|
||||
} else if ((event?.target as HTMLInputElement).id === 'gameShareFormCancel') {
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameShareFormCancel") {
|
||||
this.closeGameShare();
|
||||
}
|
||||
});
|
||||
|
||||
this.gameReportElement = new ReportMenu(this, connectionManager.getConnexionType === GameConnexionTypes.anonymous);
|
||||
this.gameReportElement = new ReportMenu(
|
||||
this,
|
||||
connectionManager.getConnexionType === GameConnexionTypes.anonymous
|
||||
);
|
||||
showReportScreenStore.subscribe((user) => {
|
||||
if (user !== null) {
|
||||
this.closeAll();
|
||||
@@ -118,17 +124,17 @@ export class MenuScene extends Phaser.Scene {
|
||||
}
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keyup-TAB', () => {
|
||||
this.input.keyboard.on("keyup-TAB", () => {
|
||||
this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu();
|
||||
});
|
||||
this.menuButton = this.add.dom(0, 0).createFromCache(gameMenuIconKey);
|
||||
this.menuButton.addListener('click');
|
||||
this.menuButton.on('click', () => {
|
||||
this.menuButton.addListener("click");
|
||||
this.menuButton.on("click", () => {
|
||||
this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu();
|
||||
});
|
||||
|
||||
this.menuElement.addListener('click');
|
||||
this.menuElement.on('click', this.onMenuClick.bind(this));
|
||||
this.menuElement.addListener("click");
|
||||
this.menuElement.on("click", this.onMenuClick.bind(this));
|
||||
|
||||
worldFullWarningStream.stream.subscribe(() => this.showWorldCapacityWarning());
|
||||
}
|
||||
@@ -145,7 +151,7 @@ export class MenuScene extends Phaser.Scene {
|
||||
public revealMenuIcon(): void {
|
||||
//TODO fix me: add try catch because at the same time, 'this.menuButton' variable doesn't exist and there is error on 'getChildByID' function
|
||||
try {
|
||||
(this.menuButton.getChildByID('menuIcon') as HTMLElement).hidden = false;
|
||||
(this.menuButton.getChildByID("menuIcon") as HTMLElement).hidden = false;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
@@ -155,22 +161,22 @@ export class MenuScene extends Phaser.Scene {
|
||||
if (this.sideMenuOpened) return;
|
||||
this.closeAll();
|
||||
this.sideMenuOpened = true;
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = 'X';
|
||||
this.menuButton.getChildByID("openMenuButton").innerHTML = "X";
|
||||
const connection = gameManager.getCurrentGameScene(this).connection;
|
||||
if (connection && connection.isAdmin()) {
|
||||
const adminSection = this.menuElement.getChildByID('adminConsoleSection') as HTMLElement;
|
||||
const adminSection = this.menuElement.getChildByID("adminConsoleSection") as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
}
|
||||
//TODO bind with future metadata of card
|
||||
//if (connectionManager.getConnexionType === GameConnexionTypes.anonymous){
|
||||
const adminSection = this.menuElement.getChildByID('socialLinks') as HTMLElement;
|
||||
const adminSection = this.menuElement.getChildByID("socialLinks") as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
//}
|
||||
this.tweens.add({
|
||||
targets: this.menuElement,
|
||||
x: openedSideMenuX,
|
||||
duration: 500,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -183,23 +189,22 @@ export class MenuScene extends Phaser.Scene {
|
||||
}
|
||||
this.warningContainerTimeout = setTimeout(() => {
|
||||
this.warningContainer?.destroy();
|
||||
this.warningContainer = null
|
||||
this.warningContainerTimeout = null
|
||||
this.warningContainer = null;
|
||||
this.warningContainerTimeout = null;
|
||||
}, 120000);
|
||||
|
||||
}
|
||||
|
||||
private closeSideMenu(): void {
|
||||
if (!this.sideMenuOpened) return;
|
||||
this.sideMenuOpened = false;
|
||||
this.closeAll();
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = `<img src="/static/images/menu.svg">`;
|
||||
this.menuButton.getChildByID("openMenuButton").innerHTML = `<img src="/static/images/menu.svg">`;
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
this.tweens.add({
|
||||
targets: this.menuElement,
|
||||
x: closedSideMenuX,
|
||||
duration: 500,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,19 +218,23 @@ export class MenuScene extends Phaser.Scene {
|
||||
|
||||
this.settingsMenuOpened = true;
|
||||
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID('select-game-quality') as HTMLInputElement;
|
||||
gameQualitySelect.value = '' + this.gameQualityValue;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID('select-video-quality') as HTMLInputElement;
|
||||
videoQualitySelect.value = '' + this.videoQualityValue;
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID("select-game-quality") as HTMLInputElement;
|
||||
gameQualitySelect.value = "" + this.gameQualityValue;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID("select-video-quality") as HTMLInputElement;
|
||||
videoQualitySelect.value = "" + this.videoQualityValue;
|
||||
|
||||
this.gameQualityMenuElement.addListener('click');
|
||||
this.gameQualityMenuElement.on('click', (event: MouseEvent) => {
|
||||
this.gameQualityMenuElement.addListener("click");
|
||||
this.gameQualityMenuElement.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if ((event?.target as HTMLInputElement).id === 'gameQualityFormSubmit') {
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID('select-game-quality') as HTMLInputElement;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID('select-video-quality') as HTMLInputElement;
|
||||
if ((event?.target as HTMLInputElement).id === "gameQualityFormSubmit") {
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID(
|
||||
"select-game-quality"
|
||||
) as HTMLInputElement;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID(
|
||||
"select-video-quality"
|
||||
) as HTMLInputElement;
|
||||
this.saveSetting(parseInt(gameQualitySelect.value), parseInt(videoQualitySelect.value));
|
||||
} else if ((event?.target as HTMLInputElement).id === 'gameQualityFormCancel') {
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameQualityFormCancel") {
|
||||
this.closeGameQualityMenu();
|
||||
}
|
||||
});
|
||||
@@ -243,7 +252,7 @@ export class MenuScene extends Phaser.Scene {
|
||||
y: middleY,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -251,16 +260,15 @@ export class MenuScene extends Phaser.Scene {
|
||||
if (!this.settingsMenuOpened) return;
|
||||
this.settingsMenuOpened = false;
|
||||
|
||||
this.gameQualityMenuElement.removeListener('click');
|
||||
this.gameQualityMenuElement.removeListener("click");
|
||||
this.tweens.add({
|
||||
targets: this.gameQualityMenuElement,
|
||||
y: -400,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private openGameShare(): void {
|
||||
if (this.gameShareOpened) {
|
||||
this.closeGameShare();
|
||||
@@ -269,7 +277,7 @@ export class MenuScene extends Phaser.Scene {
|
||||
//close all
|
||||
this.closeAll();
|
||||
|
||||
const gameShareLink = this.gameShareElement.getChildByID('gameShareLink') as HTMLInputElement;
|
||||
const gameShareLink = this.gameShareElement.getChildByID("gameShareLink") as HTMLInputElement;
|
||||
gameShareLink.value = location.toString();
|
||||
|
||||
this.gameShareOpened = true;
|
||||
@@ -287,64 +295,64 @@ export class MenuScene extends Phaser.Scene {
|
||||
y: middleY,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private closeGameShare(): void {
|
||||
const gameShareInfo = this.gameShareElement.getChildByID('gameShareInfo') as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = '';
|
||||
gameShareInfo.style.display = 'none';
|
||||
const gameShareInfo = this.gameShareElement.getChildByID("gameShareInfo") as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = "";
|
||||
gameShareInfo.style.display = "none";
|
||||
this.gameShareOpened = false;
|
||||
this.tweens.add({
|
||||
targets: this.gameShareElement,
|
||||
y: -400,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private onMenuClick(event: MouseEvent) {
|
||||
const htmlMenuItem = (event?.target as HTMLInputElement);
|
||||
if (htmlMenuItem.classList.contains('not-button')) {
|
||||
const htmlMenuItem = event?.target as HTMLInputElement;
|
||||
if (htmlMenuItem.classList.contains("not-button")) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
if (htmlMenuItem.classList.contains("fromApi")) {
|
||||
sendMenuClickedEvent(htmlMenuItem.id)
|
||||
return
|
||||
sendMenuClickedEvent(htmlMenuItem.id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((event?.target as HTMLInputElement).id) {
|
||||
case 'changeNameButton':
|
||||
case "changeNameButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(this, LoginSceneName, new LoginScene());
|
||||
break;
|
||||
case 'sparkButton':
|
||||
case "sparkButton":
|
||||
this.gotToCreateMapPage();
|
||||
break;
|
||||
case 'changeSkinButton':
|
||||
case "changeSkinButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(this, SelectCharacterSceneName, new SelectCharacterScene());
|
||||
break;
|
||||
case 'changeCompanionButton':
|
||||
case "changeCompanionButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(this, SelectCompanionSceneName, new SelectCompanionScene());
|
||||
break;
|
||||
case 'closeButton':
|
||||
case "closeButton":
|
||||
this.closeSideMenu();
|
||||
break;
|
||||
case 'shareButton':
|
||||
case "shareButton":
|
||||
this.openGameShare();
|
||||
break;
|
||||
case 'editGameSettingsButton':
|
||||
case "editGameSettingsButton":
|
||||
this.openGameSettingsMenu();
|
||||
break;
|
||||
case 'toggleFullscreen':
|
||||
case "toggleFullscreen":
|
||||
this.toggleFullscreen();
|
||||
break;
|
||||
case 'adminConsoleButton':
|
||||
case "adminConsoleButton":
|
||||
if (get(consoleGlobalMessageManagerVisibleStore)) {
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
} else {
|
||||
@@ -356,9 +364,9 @@ export class MenuScene extends Phaser.Scene {
|
||||
|
||||
private async copyLink() {
|
||||
await navigator.clipboard.writeText(location.toString());
|
||||
const gameShareInfo = this.gameShareElement.getChildByID('gameShareInfo') as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = 'Link copied, you can share it now!';
|
||||
gameShareInfo.style.display = 'block';
|
||||
const gameShareInfo = this.gameShareElement.getChildByID("gameShareInfo") as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = "Link copied, you can share it now!";
|
||||
gameShareInfo.style.display = "block";
|
||||
}
|
||||
|
||||
private saveSetting(valueGame: number, valueVideo: number) {
|
||||
@@ -378,8 +386,8 @@ export class MenuScene extends Phaser.Scene {
|
||||
private gotToCreateMapPage() {
|
||||
//const sparkHost = 'https://'+window.location.host.replace('play.', '')+'/choose-map.html';
|
||||
//TODO fix me: this button can to send us on WorkAdventure BO.
|
||||
const sparkHost = 'https://workadventu.re/getting-started';
|
||||
window.open(sparkHost, '_blank');
|
||||
const sparkHost = "https://workadventu.re/getting-started";
|
||||
window.open(sparkHost, "_blank");
|
||||
}
|
||||
|
||||
private closeAll() {
|
||||
@@ -389,10 +397,10 @@ export class MenuScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private toggleFullscreen() {
|
||||
const body = document.querySelector('body')
|
||||
const body = document.querySelector("body");
|
||||
if (body) {
|
||||
if (document.fullscreenElement ?? document.fullscreen) {
|
||||
document.exitFullscreen()
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
body.requestFullscreen();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user