Merge pull request #435 from thecodingmachine/fix/rightColumn
Rewrite the way exit detection work
This commit is contained in:
commit
4aa4a8d552
@ -6,10 +6,8 @@ export class Room {
|
|||||||
public readonly isPublic: boolean;
|
public readonly isPublic: boolean;
|
||||||
private mapUrl: string|undefined;
|
private mapUrl: string|undefined;
|
||||||
private instance: string|undefined;
|
private instance: string|undefined;
|
||||||
public readonly hash: string;
|
|
||||||
|
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
this.hash = '';
|
|
||||||
if (id.startsWith('/')) {
|
if (id.startsWith('/')) {
|
||||||
id = id.substr(1);
|
id = id.substr(1);
|
||||||
}
|
}
|
||||||
@ -24,12 +22,29 @@ export class Room {
|
|||||||
|
|
||||||
const indexOfHash = this.id.indexOf('#');
|
const indexOfHash = this.id.indexOf('#');
|
||||||
if (indexOfHash !== -1) {
|
if (indexOfHash !== -1) {
|
||||||
const idWithHash = this.id;
|
|
||||||
this.id = this.id.substr(0, indexOfHash);
|
this.id = this.id.substr(0, indexOfHash);
|
||||||
this.hash = idWithHash.substr(indexOfHash + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static getIdFromIdentifier(identifier: string, baseUrl: string, currentInstance: string): {roomId: string, hash: string} {
|
||||||
|
let roomId = '';
|
||||||
|
let hash = '';
|
||||||
|
if (!identifier.startsWith('/_/') && !identifier.startsWith('/@/')) { //relative file link
|
||||||
|
const absoluteExitSceneUrl = new URL(identifier, baseUrl);
|
||||||
|
roomId = '_/'+currentInstance+'/'+absoluteExitSceneUrl.hostname + absoluteExitSceneUrl.pathname; //in case of a relative url, we need to create a public roomId
|
||||||
|
hash = absoluteExitSceneUrl.hash;
|
||||||
|
hash = hash.substring(1); //remove the leading diese
|
||||||
|
} else { //absolute room Id
|
||||||
|
const parts = identifier.split('#');
|
||||||
|
roomId = parts[0];
|
||||||
|
roomId = roomId.substring(1); //remove the leading slash
|
||||||
|
if (parts.length > 1) {
|
||||||
|
hash = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {roomId, hash}
|
||||||
|
}
|
||||||
|
|
||||||
public async getMapUrl(): Promise<string> {
|
public async getMapUrl(): Promise<string> {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
if (this.mapUrl !== undefined) {
|
if (this.mapUrl !== undefined) {
|
||||||
|
@ -52,6 +52,7 @@ export class RoomConnection implements RoomConnection {
|
|||||||
private static websocketFactory: null|((url: string)=>any) = null; // eslint-disable-line @typescript-eslint/no-explicit-any
|
private static websocketFactory: null|((url: string)=>any) = null; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
private closed: boolean = false;
|
private closed: boolean = false;
|
||||||
private tags: string[] = [];
|
private tags: string[] = [];
|
||||||
|
private intervalId!: NodeJS.Timeout;
|
||||||
|
|
||||||
public static setWebsocketFactory(websocketFactory: (url: string)=>any): void { // eslint-disable-line @typescript-eslint/no-explicit-any
|
public static setWebsocketFactory(websocketFactory: (url: string)=>any): void { // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
RoomConnection.websocketFactory = websocketFactory;
|
RoomConnection.websocketFactory = websocketFactory;
|
||||||
@ -89,9 +90,13 @@ export class RoomConnection implements RoomConnection {
|
|||||||
this.socket.onopen = (ev) => {
|
this.socket.onopen = (ev) => {
|
||||||
//we manually ping every 20s to not be logged out by the server, even when the game is in background.
|
//we manually ping every 20s to not be logged out by the server, even when the game is in background.
|
||||||
const pingMessage = new PingMessage();
|
const pingMessage = new PingMessage();
|
||||||
setInterval(() => this.socket.send(pingMessage.serializeBinary().buffer), manualPingDelay);
|
this.intervalId = setInterval(() => this.socket.send(pingMessage.serializeBinary().buffer), manualPingDelay);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.socket.onclose = () => {
|
||||||
|
clearTimeout(this.intervalId);
|
||||||
|
}
|
||||||
|
|
||||||
this.socket.onmessage = (messageEvent) => {
|
this.socket.onmessage = (messageEvent) => {
|
||||||
const arrayBuffer: ArrayBuffer = messageEvent.data;
|
const arrayBuffer: ArrayBuffer = messageEvent.data;
|
||||||
const message = ServerToClientMessage.deserializeBinary(new Uint8Array(arrayBuffer));
|
const message = ServerToClientMessage.deserializeBinary(new Uint8Array(arrayBuffer));
|
||||||
|
@ -39,20 +39,16 @@ export class GameManager {
|
|||||||
public async loadMap(room: Room, scenePlugin: Phaser.Scenes.ScenePlugin): Promise<void> {
|
public async loadMap(room: Room, scenePlugin: Phaser.Scenes.ScenePlugin): Promise<void> {
|
||||||
const roomID = room.id;
|
const roomID = room.id;
|
||||||
const mapUrl = await room.getMapUrl();
|
const mapUrl = await room.getMapUrl();
|
||||||
console.log('Loading map '+roomID+' at url '+mapUrl);
|
|
||||||
|
|
||||||
const gameIndex = scenePlugin.getIndex(mapUrl);
|
const gameIndex = scenePlugin.getIndex(roomID);
|
||||||
if(gameIndex === -1){
|
if(gameIndex === -1){
|
||||||
const game : Phaser.Scene = GameScene.createFromUrl(room, mapUrl);
|
const game : Phaser.Scene = new GameScene(room, mapUrl);
|
||||||
console.log('Adding scene '+mapUrl);
|
scenePlugin.add(roomID, game, false);
|
||||||
scenePlugin.add(mapUrl, game, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async goToStartingMap(scenePlugin: Phaser.Scenes.ScenePlugin) {
|
public goToStartingMap(scenePlugin: Phaser.Scenes.ScenePlugin): void {
|
||||||
const url = await this.startRoom.getMapUrl();
|
scenePlugin.start(this.startRoom.id);
|
||||||
console.log('Starting scene '+url);
|
|
||||||
scenePlugin.start(url);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ import {ConsoleGlobalMessageManager} from "../../Administration/ConsoleGlobalMes
|
|||||||
import {ResizableScene} from "../Login/ResizableScene";
|
import {ResizableScene} from "../Login/ResizableScene";
|
||||||
import {Room} from "../../Connexion/Room";
|
import {Room} from "../../Connexion/Room";
|
||||||
import {jitsiFactory} from "../../WebRtc/JitsiFactory";
|
import {jitsiFactory} from "../../WebRtc/JitsiFactory";
|
||||||
|
import {urlManager} from "../../Url/UrlManager";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface|null
|
initPosition: PointInterface|null
|
||||||
@ -94,6 +95,8 @@ interface DeleteGroupEventInterface {
|
|||||||
groupId: number
|
groupId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultStartLayerName = 'start';
|
||||||
|
|
||||||
export class GameScene extends ResizableScene implements CenterListener {
|
export class GameScene extends ResizableScene implements CenterListener {
|
||||||
GameManager : GameManager;
|
GameManager : GameManager;
|
||||||
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
||||||
@ -123,7 +126,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
private createPromise: Promise<void>;
|
private createPromise: Promise<void>;
|
||||||
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
|
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
|
||||||
|
|
||||||
MapKey: string;
|
|
||||||
MapUrlFile: string;
|
MapUrlFile: string;
|
||||||
RoomId: string;
|
RoomId: string;
|
||||||
instance: string;
|
instance: string;
|
||||||
@ -137,7 +139,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
y: -1000
|
y: -1000
|
||||||
}
|
}
|
||||||
|
|
||||||
private PositionNextScene: Array<Array<{ key: string, hash: string }>> = new Array<Array<{ key: string, hash: string }>>();
|
|
||||||
private presentationModeSprite!: Sprite;
|
private presentationModeSprite!: Sprite;
|
||||||
private chatModeSprite!: Sprite;
|
private chatModeSprite!: Sprite;
|
||||||
private gameMap!: GameMap;
|
private gameMap!: GameMap;
|
||||||
@ -145,18 +146,11 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
// The item that can be selected by pressing the space key.
|
// The item that can be selected by pressing the space key.
|
||||||
private outlinedItem: ActionableItem|null = null;
|
private outlinedItem: ActionableItem|null = null;
|
||||||
private userInputManager!: UserInputManager;
|
private userInputManager!: UserInputManager;
|
||||||
|
private startLayerName!: string | null;
|
||||||
|
|
||||||
static createFromUrl(room: Room, mapUrlFile: string, gameSceneKey: string|null = null): GameScene {
|
constructor(private room: Room, MapUrlFile: string) {
|
||||||
// We use the map URL as a key
|
|
||||||
if (gameSceneKey === null) {
|
|
||||||
gameSceneKey = mapUrlFile;
|
|
||||||
}
|
|
||||||
return new GameScene(room, mapUrlFile, gameSceneKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(private room: Room, MapUrlFile: string, gameSceneKey: string) {
|
|
||||||
super({
|
super({
|
||||||
key: gameSceneKey
|
key: room.id
|
||||||
});
|
});
|
||||||
|
|
||||||
this.GameManager = gameManager;
|
this.GameManager = gameManager;
|
||||||
@ -164,7 +158,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
this.groups = new Map<number, Sprite>();
|
this.groups = new Map<number, Sprite>();
|
||||||
this.instance = room.getInstance();
|
this.instance = room.getInstance();
|
||||||
|
|
||||||
this.MapKey = MapUrlFile;
|
|
||||||
this.MapUrlFile = MapUrlFile;
|
this.MapUrlFile = MapUrlFile;
|
||||||
this.RoomId = room.id;
|
this.RoomId = room.id;
|
||||||
|
|
||||||
@ -183,15 +176,15 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
file: file.src
|
file: file.src
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.load.on('filecomplete-tilemapJSON-'+this.MapKey, (key: string, type: string, data: unknown) => {
|
this.load.on('filecomplete-tilemapJSON-'+this.MapUrlFile, (key: string, type: string, data: unknown) => {
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data);
|
||||||
});
|
});
|
||||||
//TODO strategy to add access token
|
//TODO strategy to add access token
|
||||||
this.load.tilemapTiledJSON(this.MapKey, this.MapUrlFile);
|
this.load.tilemapTiledJSON(this.MapUrlFile, this.MapUrlFile);
|
||||||
// If the map has already been loaded as part of another GameScene, the "on load" event will not be triggered.
|
// If the map has already been loaded as part of another GameScene, the "on load" event will not be triggered.
|
||||||
// In this case, we check in the cache to see if the map is here and trigger the event manually.
|
// In this case, we check in the cache to see if the map is here and trigger the event manually.
|
||||||
if (this.cache.tilemap.exists(this.MapKey)) {
|
if (this.cache.tilemap.exists(this.MapUrlFile)) {
|
||||||
const data = this.cache.tilemap.get(this.MapKey);
|
const data = this.cache.tilemap.get(this.MapUrlFile);
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,14 +295,16 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
//hook initialisation
|
//hook initialisation
|
||||||
init(initData : GameSceneInitInterface) {
|
init(initData : GameSceneInitInterface) {
|
||||||
if (initData.initPosition !== undefined) {
|
if (initData.initPosition !== undefined) {
|
||||||
this.initPosition = initData.initPosition;
|
this.initPosition = initData.initPosition; //todo: still used?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//hook create scene
|
//hook create scene
|
||||||
create(): void {
|
create(): void {
|
||||||
|
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||||
|
|
||||||
//initalise map
|
//initalise map
|
||||||
this.Map = this.add.tilemap(this.MapKey);
|
this.Map = this.add.tilemap(this.MapUrlFile);
|
||||||
this.gameMap = new GameMap(this.mapFile);
|
this.gameMap = new GameMap(this.mapFile);
|
||||||
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
|
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
|
||||||
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
|
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
|
||||||
@ -319,25 +314,21 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
//permit to set bound collision
|
//permit to set bound collision
|
||||||
this.physics.world.setBounds(0, 0, this.Map.widthInPixels, this.Map.heightInPixels);
|
this.physics.world.setBounds(0, 0, this.Map.widthInPixels, this.Map.heightInPixels);
|
||||||
|
|
||||||
// Let's alter browser history
|
|
||||||
let path = this.room.id;
|
|
||||||
if (this.room.hash) {
|
|
||||||
path += '#' + this.room.hash;
|
|
||||||
}
|
|
||||||
window.history.pushState({}, 'WorkAdventure', path);
|
|
||||||
|
|
||||||
//add layer on map
|
//add layer on map
|
||||||
this.Layers = new Array<Phaser.Tilemaps.StaticTilemapLayer>();
|
this.Layers = new Array<Phaser.Tilemaps.StaticTilemapLayer>();
|
||||||
let depth = -2;
|
let depth = -2;
|
||||||
for (const layer of this.mapFile.layers) {
|
for (const layer of this.mapFile.layers) {
|
||||||
if (layer.type === 'tilelayer') {
|
if (layer.type === 'tilelayer') {
|
||||||
this.addLayer(this.Map.createStaticLayer(layer.name, this.Terrains, 0, 0).setDepth(depth));
|
this.addLayer(this.Map.createStaticLayer(layer.name, this.Terrains, 0, 0).setDepth(depth));
|
||||||
}
|
|
||||||
if (layer.type === 'tilelayer' && this.getExitSceneUrl(layer) !== undefined) {
|
const exitSceneUrl = this.getExitSceneUrl(layer);
|
||||||
this.loadNextGameFromExitSceneUrl(layer, this.mapFile.width);
|
if (exitSceneUrl !== undefined) {
|
||||||
} else if (layer.type === 'tilelayer' && this.getExitUrl(layer) !== undefined) {
|
this.loadNextGame(exitSceneUrl);
|
||||||
console.log('Loading exitUrl ', this.getExitUrl(layer))
|
}
|
||||||
this.loadNextGameFromExitUrl(layer, this.mapFile.width);
|
const exitUrl = this.getExitUrl(layer);
|
||||||
|
if (exitUrl !== undefined) {
|
||||||
|
this.loadNextGame(exitUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (layer.type === 'objectgroup' && layer.name === 'floorLayer') {
|
if (layer.type === 'objectgroup' && layer.name === 'floorLayer') {
|
||||||
depth = 10000;
|
depth = 10000;
|
||||||
@ -482,7 +473,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
if (position === undefined) {
|
if (position === undefined) {
|
||||||
throw new Error('Position missing from UserMovedMessage');
|
throw new Error('Position missing from UserMovedMessage');
|
||||||
}
|
}
|
||||||
//console.log('Received position ', position.getX(), position.getY(), "from user", message.getUserid());
|
|
||||||
|
|
||||||
const messageUserMoved: MessageUserMovedInterface = {
|
const messageUserMoved: MessageUserMovedInterface = {
|
||||||
userId: message.getUserid(),
|
userId: message.getUserid(),
|
||||||
@ -515,7 +505,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
this.simplePeer.unregister();
|
this.simplePeer.unregister();
|
||||||
|
|
||||||
const gameSceneKey = 'somekey' + Math.round(Math.random() * 10000);
|
const gameSceneKey = 'somekey' + Math.round(Math.random() * 10000);
|
||||||
const game: Phaser.Scene = GameScene.createFromUrl(this.room, this.MapUrlFile, gameSceneKey);
|
const game: Phaser.Scene = new GameScene(this.room, this.MapUrlFile);
|
||||||
this.scene.add(gameSceneKey, game, true,
|
this.scene.add(gameSceneKey, game, true,
|
||||||
{
|
{
|
||||||
initPosition: {
|
initPosition: {
|
||||||
@ -581,6 +571,12 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private triggerOnMapLayerPropertyChange(){
|
private triggerOnMapLayerPropertyChange(){
|
||||||
|
this.gameMap.onPropertyChange('exitSceneUrl', (newValue, oldValue) => {
|
||||||
|
if (newValue) this.onMapExit(newValue as string);
|
||||||
|
});
|
||||||
|
this.gameMap.onPropertyChange('exitUrl', (newValue, oldValue) => {
|
||||||
|
if (newValue) this.onMapExit(newValue as string);
|
||||||
|
});
|
||||||
this.gameMap.onPropertyChange('openWebsite', (newValue, oldValue, allProps) => {
|
this.gameMap.onPropertyChange('openWebsite', (newValue, oldValue, allProps) => {
|
||||||
if (newValue === undefined) {
|
if (newValue === undefined) {
|
||||||
layoutManager.removeActionButton('openWebsite', this.userInputManager);
|
layoutManager.removeActionButton('openWebsite', this.userInputManager);
|
||||||
@ -636,6 +632,25 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onMapExit(exitKey: string) {
|
||||||
|
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 (roomId !== this.scene.key) {
|
||||||
|
// We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map.
|
||||||
|
this.connection.closeConnection();
|
||||||
|
this.simplePeer.unregister();
|
||||||
|
this.scene.stop();
|
||||||
|
this.scene.remove(this.scene.key);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private switchLayoutMode(): void {
|
private switchLayoutMode(): void {
|
||||||
//if discussion is activated, this layout cannot be activated
|
//if discussion is activated, this layout cannot be activated
|
||||||
if(mediaManager.activatedDiscussion){
|
if(mediaManager.activatedDiscussion){
|
||||||
@ -660,12 +675,12 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
this.startY = this.initPosition.y;
|
this.startY = this.initPosition.y;
|
||||||
} else {
|
} else {
|
||||||
// Now, let's find the start layer
|
// Now, let's find the start layer
|
||||||
if (this.room.hash) {
|
if (this.startLayerName) {
|
||||||
this.initPositionFromLayerName(this.room.hash);
|
this.initPositionFromLayerName(this.startLayerName);
|
||||||
}
|
}
|
||||||
if (this.startX === undefined) {
|
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.
|
// 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("start");
|
this.initPositionFromLayerName(defaultStartLayerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Still no start position? Something is wrong with the map, we need a "start" layer.
|
// Still no start position? Something is wrong with the map, we need a "start" layer.
|
||||||
@ -679,7 +694,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
private initPositionFromLayerName(layerName: string) {
|
private initPositionFromLayerName(layerName: string) {
|
||||||
for (const layer of this.mapFile.layers) {
|
for (const layer of this.mapFile.layers) {
|
||||||
if (layerName === layer.name && layer.type === 'tilelayer' && (layerName === "start" || this.isStartLayer(layer))) {
|
if (layerName === layer.name && layer.type === 'tilelayer' && (layerName === defaultStartLayerName || this.isStartLayer(layer))) {
|
||||||
const startPosition = this.startUser(layer);
|
const startPosition = this.startUser(layer);
|
||||||
this.startX = startPosition.x;
|
this.startX = startPosition.x;
|
||||||
this.startY = startPosition.y;
|
this.startY = startPosition.y;
|
||||||
@ -691,14 +706,13 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
return this.getProperty(layer, "exitUrl") as string|undefined;
|
return this.getProperty(layer, "exitUrl") as string|undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated the map property exitSceneUrl is deprecated
|
||||||
|
*/
|
||||||
private getExitSceneUrl(layer: ITiledMapLayer): string|undefined {
|
private getExitSceneUrl(layer: ITiledMapLayer): string|undefined {
|
||||||
return this.getProperty(layer, "exitSceneUrl") as string|undefined;
|
return this.getProperty(layer, "exitSceneUrl") as string|undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getExitSceneInstance(layer: ITiledMapLayer): string|undefined {
|
|
||||||
return this.getProperty(layer, "exitInstance") as string|undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isStartLayer(layer: ITiledMapLayer): boolean {
|
private isStartLayer(layer: ITiledMapLayer): boolean {
|
||||||
return this.getProperty(layer, "startLayer") == true;
|
return this.getProperty(layer, "startLayer") == true;
|
||||||
}
|
}
|
||||||
@ -715,66 +729,11 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
return obj.value;
|
return obj.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadNextGameFromExitSceneUrl(layer: ITiledMapLayer, mapWidth: number) {
|
|
||||||
const exitSceneUrl = this.getExitSceneUrl(layer);
|
|
||||||
if (exitSceneUrl === undefined) {
|
|
||||||
throw new Error('Layer is not an exit scene layer.');
|
|
||||||
}
|
|
||||||
let instance = this.getExitSceneInstance(layer);
|
|
||||||
if (instance === undefined) {
|
|
||||||
instance = this.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const absoluteExitSceneUrl = new URL(exitSceneUrl, this.MapUrlFile).href;
|
|
||||||
const absoluteExitSceneUrlWithoutProtocol = absoluteExitSceneUrl.toString().substr(absoluteExitSceneUrl.toString().indexOf('://')+3);
|
|
||||||
const roomId = '_/'+instance+'/'+absoluteExitSceneUrlWithoutProtocol;
|
|
||||||
|
|
||||||
this.loadNextGame(layer, mapWidth, roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadNextGameFromExitUrl(layer: ITiledMapLayer, mapWidth: number) {
|
|
||||||
const exitUrl = this.getExitUrl(layer);
|
|
||||||
if (exitUrl === undefined) {
|
|
||||||
throw new Error('Layer is not an exit layer.');
|
|
||||||
}
|
|
||||||
const fullPath = new URL(exitUrl, window.location.toString()).pathname;
|
|
||||||
|
|
||||||
this.loadNextGame(layer, mapWidth, fullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
//todo: push that into the gameManager
|
//todo: push that into the gameManager
|
||||||
private loadNextGame(layer: ITiledMapLayer, mapWidth: number, roomId: string){
|
private async loadNextGame(exitSceneIdentifier: string){
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier(exitSceneIdentifier, this.MapUrlFile, this.instance);
|
||||||
const room = new Room(roomId);
|
const room = new Room(roomId);
|
||||||
gameManager.loadMap(room, this.scene);
|
await gameManager.loadMap(room, this.scene);
|
||||||
const exitSceneKey = roomId;
|
|
||||||
|
|
||||||
const tiles : number[] = layer.data as number[];
|
|
||||||
for (let key=0; key < tiles.length; key++) {
|
|
||||||
const objectKey = tiles[key];
|
|
||||||
if(objectKey === 0){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//key + 1 because the start x = 0;
|
|
||||||
const y : number = parseInt(((key + 1) / mapWidth).toString());
|
|
||||||
const x : number = key - (y * mapWidth);
|
|
||||||
|
|
||||||
let hash = new URL(roomId, this.MapUrlFile).hash;
|
|
||||||
if (hash) {
|
|
||||||
hash = hash.substr(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//push and save switching case
|
|
||||||
if (this.PositionNextScene[y] === undefined) {
|
|
||||||
this.PositionNextScene[y] = new Array<{key: string, hash: string}>();
|
|
||||||
}
|
|
||||||
room.getMapUrl().then((url: string) => {
|
|
||||||
this.PositionNextScene[y][x] = {
|
|
||||||
key: url,
|
|
||||||
hash
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private startUser(layer: ITiledMapLayer): PositionInterface {
|
private startUser(layer: ITiledMapLayer): PositionInterface {
|
||||||
@ -975,33 +934,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
}
|
}
|
||||||
player.updatePosition(moveEvent);
|
player.updatePosition(moveEvent);
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextSceneKey = this.checkToExit();
|
|
||||||
if (!nextSceneKey) return;
|
|
||||||
if (nextSceneKey.key !== this.scene.key) {
|
|
||||||
// We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map.
|
|
||||||
this.connection.closeConnection();
|
|
||||||
this.simplePeer.unregister();
|
|
||||||
this.scene.stop();
|
|
||||||
this.scene.remove(this.scene.key);
|
|
||||||
this.scene.start(nextSceneKey.key);
|
|
||||||
} else {
|
|
||||||
//if the exit points to the current map, we simply teleport the user back to the startLayer
|
|
||||||
this.initPositionFromLayerName(this.room.hash || 'start');
|
|
||||||
this.CurrentPlayer.x = this.startX;
|
|
||||||
this.CurrentPlayer.y = this.startY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private checkToExit(): {key: string, hash: string} | null {
|
|
||||||
const x = Math.floor(this.CurrentPlayer.x / 32);
|
|
||||||
const y = Math.floor(this.CurrentPlayer.y / 32);
|
|
||||||
|
|
||||||
if (this.PositionNextScene[y] !== undefined && this.PositionNextScene[y][x] !== undefined) {
|
|
||||||
return this.PositionNextScene[y][x];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +45,14 @@ class UrlManager {
|
|||||||
return newUrl;
|
return newUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getStartLayerNameFromUrl(): string|null {
|
||||||
|
const hash = window.location.hash;
|
||||||
|
return hash.length > 1 ? hash.substring(1) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushStartLayerNameToUrl(startLayerName: string): void {
|
||||||
|
window.location.hash = startLayerName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const urlManager = new UrlManager();
|
export const urlManager = new UrlManager();
|
||||||
|
42
front/tests/Phaser/Game/RoomTest.ts
Normal file
42
front/tests/Phaser/Game/RoomTest.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import "jasmine";
|
||||||
|
import {Room} from "../../../src/Connexion/Room";
|
||||||
|
|
||||||
|
describe("Room getIdFromIdentifier()", () => {
|
||||||
|
it("should work with an absolute room id and no hash as parameter", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('/_/global/maps.workadventu.re/test2.json', '', '');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/test2.json');
|
||||||
|
expect(hash).toEqual('');
|
||||||
|
});
|
||||||
|
it("should work with an absolute room id and a hash as parameters", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('/_/global/maps.workadventu.re/test2.json#start', '', '');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/test2.json');
|
||||||
|
expect(hash).toEqual("start");
|
||||||
|
});
|
||||||
|
it("should work with an absolute room id, regardless of baseUrl or instance", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('/_/global/maps.workadventu.re/test2.json', 'https://another.domain/_/global/test.json', 'lol');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/test2.json');
|
||||||
|
expect(hash).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("should work with a relative file link and no hash as parameters", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('./test2.json', 'https://maps.workadventu.re/test.json', 'global');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/test2.json');
|
||||||
|
expect(hash).toEqual('');
|
||||||
|
});
|
||||||
|
it("should work with a relative file link with no dot", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('test2.json', 'https://maps.workadventu.re/test.json', 'global');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/test2.json');
|
||||||
|
expect(hash).toEqual('');
|
||||||
|
});
|
||||||
|
it("should work with a relative file link two levels deep", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('../floor1/Floor1.json', 'https://maps.workadventu.re/floor0/Floor0.json', 'global');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/floor1/Floor1.json');
|
||||||
|
expect(hash).toEqual('');
|
||||||
|
});
|
||||||
|
it("should work with a relative file link and a hash as parameters", () => {
|
||||||
|
const {roomId, hash} = Room.getIdFromIdentifier('./test2.json#start', 'https://maps.workadventu.re/test.json', 'global');
|
||||||
|
expect(roomId).toEqual('_/global/maps.workadventu.re/test2.json');
|
||||||
|
expect(hash).toEqual("start");
|
||||||
|
});
|
||||||
|
});
|
1
maps/.gitignore
vendored
1
maps/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/node_modules/
|
/node_modules/
|
||||||
|
dist/
|
1577
maps/yarn.lock
Normal file
1577
maps/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user