Refactoring reconnection: putting it into the GameScene directly.
This commit is contained in:
parent
d785a8a1bf
commit
f88f28db3f
@ -124,7 +124,7 @@ export interface StartMapInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Connection implements Connection {
|
export class Connection implements Connection {
|
||||||
socket: Socket|null = null;
|
socket: Socket;
|
||||||
token: string|null = null;
|
token: string|null = null;
|
||||||
name: string|null = null; // TODO: drop "name" storage here
|
name: string|null = null; // TODO: drop "name" storage here
|
||||||
character: string|null = null;
|
character: string|null = null;
|
||||||
@ -135,53 +135,59 @@ export class Connection implements Connection {
|
|||||||
lastPositionShared: PointInterface|null = null;
|
lastPositionShared: PointInterface|null = null;
|
||||||
lastRoom: string|null = null;
|
lastRoom: string|null = null;
|
||||||
|
|
||||||
private constructor(GameManager: GameManager) {
|
private constructor(GameManager: GameManager, name: string, character: string, token: string) {
|
||||||
this.GameManager = GameManager;
|
this.GameManager = GameManager;
|
||||||
|
this.name = name;
|
||||||
|
this.character = character;
|
||||||
|
this.token = token;
|
||||||
|
|
||||||
|
this.socket = SocketIo(`${API_URL}`, {
|
||||||
|
query: {
|
||||||
|
token: this.token
|
||||||
|
},
|
||||||
|
reconnection: false // Reconnection is handled by the application itself
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on(EventMessage.CONNECT_ERROR, () => {
|
||||||
|
console.error("Connection failed")
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on(EventMessage.MESSAGE_ERROR, (message: string) => {
|
||||||
|
console.error(EventMessage.MESSAGE_ERROR, message);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createConnection(name: string, characterSelected: string): Promise<Connection> {
|
public static createConnection(name: string, characterSelected: string): Promise<Connection> {
|
||||||
let connection = new Connection(gameManager);
|
|
||||||
connection.name = name;
|
|
||||||
connection.character = characterSelected;
|
|
||||||
return Axios.post(`${API_URL}/login`, {name: name})
|
return Axios.post(`${API_URL}/login`, {name: name})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
connection.token = res.data.token;
|
let connection = new Connection(gameManager, name, characterSelected, res.data.token);
|
||||||
connection.socket = SocketIo(`${API_URL}`, {
|
|
||||||
query: {
|
|
||||||
token: connection.token
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//listen event
|
|
||||||
connection.disconnectServer();
|
|
||||||
connection.errorMessage();
|
|
||||||
|
|
||||||
|
// FIXME: we should wait for the complete connexion here (i.e. the "connected" message from socket.io)!
|
||||||
|
// Otherwise, the connection MAY fail and we will never know!
|
||||||
return connection.connectSocketServer();
|
return connection.connectSocketServer();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
// Let's retry in 4-6 seconds
|
||||||
throw err;
|
return new Promise<Connection>((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(Connection.createConnection(name, characterSelected));
|
||||||
|
}, 4000 + Math.floor(Math.random() * 2000) );
|
||||||
|
});
|
||||||
|
|
||||||
|
//console.error(err);
|
||||||
|
//throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeConnection(): void {
|
public closeConnection(): void {
|
||||||
this.socket?.close();
|
this.socket?.close();
|
||||||
this.socket = null;
|
|
||||||
this.lastPositionShared = null;
|
this.lastPositionShared = null;
|
||||||
this.lastRoom = null;
|
this.lastRoom = null;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private getSocket(): Socket {
|
|
||||||
if (this.socket === null) {
|
|
||||||
throw new Error('Socket not initialized while using Connection')
|
|
||||||
}
|
|
||||||
return this.socket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connectSocketServer(): Promise<Connection>{
|
connectSocketServer(): Promise<Connection>{
|
||||||
return new Promise<Connection>((resolve, reject) => {
|
return new Promise<Connection>((resolve, reject) => {
|
||||||
this.getSocket().emit(EventMessage.SET_PLAYER_DETAILS, {
|
this.socket.emit(EventMessage.SET_PLAYER_DETAILS, {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
character: this.character
|
character: this.character
|
||||||
} as SetPlayerDetailsMessage, (id: string) => {
|
} as SetPlayerDetailsMessage, (id: string) => {
|
||||||
@ -218,7 +224,7 @@ export class Connection implements Connection {
|
|||||||
const point = new Point(startX, startY, direction, moving);
|
const point = new Point(startX, startY, direction, moving);
|
||||||
this.lastPositionShared = point;
|
this.lastPositionShared = point;
|
||||||
let promise = new Promise<MessageUserPositionInterface[]>((resolve, reject) => {
|
let promise = new Promise<MessageUserPositionInterface[]>((resolve, reject) => {
|
||||||
this.getSocket().emit(EventMessage.JOIN_ROOM, { roomId, position: {x: startX, y: startY, direction, moving }}, (userPositions: MessageUserPositionInterface[]) => {
|
this.socket.emit(EventMessage.JOIN_ROOM, { roomId, position: {x: startX, y: startY, direction, moving }}, (userPositions: MessageUserPositionInterface[]) => {
|
||||||
//this.GameManager.initUsersPosition(userPositions);
|
//this.GameManager.initUsersPosition(userPositions);
|
||||||
resolve(userPositions);
|
resolve(userPositions);
|
||||||
});
|
});
|
||||||
@ -233,31 +239,31 @@ export class Connection implements Connection {
|
|||||||
}
|
}
|
||||||
const point = new Point(x, y, direction, moving);
|
const point = new Point(x, y, direction, moving);
|
||||||
this.lastPositionShared = point;
|
this.lastPositionShared = point;
|
||||||
this.getSocket().emit(EventMessage.USER_POSITION, point);
|
this.socket.emit(EventMessage.USER_POSITION, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onUserJoins(callback: (message: MessageUserJoined) => void): void {
|
public onUserJoins(callback: (message: MessageUserJoined) => void): void {
|
||||||
this.getSocket().on(EventMessage.JOIN_ROOM, callback);
|
this.socket.on(EventMessage.JOIN_ROOM, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onUserMoved(callback: (message: MessageUserMovedInterface) => void): void {
|
public onUserMoved(callback: (message: MessageUserMovedInterface) => void): void {
|
||||||
this.getSocket().on(EventMessage.USER_MOVED, callback);
|
this.socket.on(EventMessage.USER_MOVED, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onUserLeft(callback: (userId: string) => void): void {
|
public onUserLeft(callback: (userId: string) => void): void {
|
||||||
this.getSocket().on(EventMessage.USER_LEFT, callback);
|
this.socket.on(EventMessage.USER_LEFT, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onGroupUpdatedOrCreated(callback: (groupCreateUpdateMessage: GroupCreatedUpdatedMessageInterface) => void): void {
|
public onGroupUpdatedOrCreated(callback: (groupCreateUpdateMessage: GroupCreatedUpdatedMessageInterface) => void): void {
|
||||||
this.getSocket().on(EventMessage.GROUP_CREATE_UPDATE, callback);
|
this.socket.on(EventMessage.GROUP_CREATE_UPDATE, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onGroupDeleted(callback: (groupId: string) => void): void {
|
public onGroupDeleted(callback: (groupId: string) => void): void {
|
||||||
this.getSocket().on(EventMessage.GROUP_DELETE, callback)
|
this.socket.on(EventMessage.GROUP_DELETE, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWebrtcSignal(signal: unknown, roomId: string, userId? : string|null, receiverId? : string) {
|
sendWebrtcSignal(signal: unknown, roomId: string, userId? : string|null, receiverId? : string) {
|
||||||
return this.getSocket().emit(EventMessage.WEBRTC_SIGNAL, {
|
return this.socket.emit(EventMessage.WEBRTC_SIGNAL, {
|
||||||
userId: userId ? userId : this.userId,
|
userId: userId ? userId : this.userId,
|
||||||
receiverId: receiverId ? receiverId : this.userId,
|
receiverId: receiverId ? receiverId : this.userId,
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
@ -266,47 +272,53 @@ export class Connection implements Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
receiveWebrtcStart(callback: (message: WebRtcStartMessageInterface) => void) {
|
receiveWebrtcStart(callback: (message: WebRtcStartMessageInterface) => void) {
|
||||||
this.getSocket().on(EventMessage.WEBRTC_START, callback);
|
this.socket.on(EventMessage.WEBRTC_START, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveWebrtcSignal(callback: (message: WebRtcSignalMessageInterface) => void) {
|
receiveWebrtcSignal(callback: (message: WebRtcSignalMessageInterface) => void) {
|
||||||
return this.getSocket().on(EventMessage.WEBRTC_SIGNAL, callback);
|
return this.socket.on(EventMessage.WEBRTC_SIGNAL, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private errorMessage(): void {
|
public onServerDisconnected(callback: (reason: string) => void): void {
|
||||||
this.getSocket().on(EventMessage.MESSAGE_ERROR, (message: string) => {
|
/*this.socket.on(EventMessage.CONNECT_ERROR, (error: object) => {
|
||||||
console.error(EventMessage.MESSAGE_ERROR, message);
|
callback(error);
|
||||||
})
|
});*/
|
||||||
}
|
|
||||||
|
|
||||||
private disconnectServer(): void {
|
this.socket.on('disconnect', (reason: string) => {
|
||||||
this.getSocket().on(EventMessage.CONNECT_ERROR, () => {
|
if (reason === 'io client disconnect') {
|
||||||
this.GameManager.switchToDisconnectedScene();
|
// The client asks for disconnect, let's not trigger any event.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getSocket().on(EventMessage.RECONNECTING, () => {
|
/*this.socket.on(EventMessage.CONNECT_ERROR, (error: object) => {
|
||||||
|
this.GameManager.switchToDisconnectedScene();
|
||||||
|
});*/
|
||||||
|
|
||||||
|
/*this.socket.on(EventMessage.RECONNECTING, () => {
|
||||||
console.log('Trying to reconnect');
|
console.log('Trying to reconnect');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getSocket().on(EventMessage.RECONNECT_ERROR, () => {
|
this.socket.on(EventMessage.RECONNECT_ERROR, () => {
|
||||||
console.log('Error while trying to reconnect.');
|
console.log('Error while trying to reconnect.');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getSocket().on(EventMessage.RECONNECT_FAILED, () => {
|
this.socket.on(EventMessage.RECONNECT_FAILED, () => {
|
||||||
console.error('Reconnection failed. Giving up.');
|
console.error('Reconnection failed. Giving up.');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getSocket().on(EventMessage.RECONNECT, () => {
|
this.socket.on(EventMessage.RECONNECT, () => {
|
||||||
console.log('Reconnect event triggered');
|
console.log('Reconnect event triggered');
|
||||||
this.connectSocketServer();
|
this.connectSocketServer();
|
||||||
if (this.lastPositionShared === null) {
|
if (this.lastPositionShared === null) {
|
||||||
throw new Error('No last position shared found while reconnecting');
|
throw new Error('No last position shared found while reconnecting');
|
||||||
}
|
}
|
||||||
this.GameManager.reconnectToGameScene(this.lastPositionShared);
|
this.GameManager.reconnectToGameScene(this.lastPositionShared);
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectMessage(callback: (message: WebRtcDisconnectMessageInterface) => void): void {
|
disconnectMessage(callback: (message: WebRtcDisconnectMessageInterface) => void): void {
|
||||||
this.getSocket().on(EventMessage.WEBRTC_DISCONNECT, callback);
|
this.socket.on(EventMessage.WEBRTC_DISCONNECT, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ export class GameManager {
|
|||||||
this.currentGameScene = null;
|
this.currentGameScene = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private timeoutCallback: NodeJS.Timeout|null = null;
|
/*private timeoutCallback: NodeJS.Timeout|null = null;
|
||||||
reconnectToGameScene(lastPositionShared: PointInterface): void {
|
reconnectToGameScene(lastPositionShared: PointInterface): void {
|
||||||
if (this.timeoutCallback !== null) {
|
if (this.timeoutCallback !== null) {
|
||||||
console.log('Reconnect called but setTimeout in progress for the reconnection');
|
console.log('Reconnect called but setTimeout in progress for the reconnection');
|
||||||
@ -150,7 +150,7 @@ export class GameManager {
|
|||||||
const game : Phaser.Scene = GameScene.createFromUrl(this.oldMapUrlFile, this.oldInstance);
|
const game : Phaser.Scene = GameScene.createFromUrl(this.oldMapUrlFile, this.oldInstance);
|
||||||
this.reconnectScene.scene.add(this.oldSceneKey, game, true, { initPosition: lastPositionShared });
|
this.reconnectScene.scene.add(this.oldSceneKey, game, true, { initPosition: lastPositionShared });
|
||||||
this.reconnectScene = null;
|
this.reconnectScene = null;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private getCurrentGameScene(): GameScene {
|
private getCurrentGameScene(): GameScene {
|
||||||
if (this.currentGameScene === null) {
|
if (this.currentGameScene === null) {
|
||||||
|
@ -25,6 +25,7 @@ import {RemotePlayer} from "../Entity/RemotePlayer";
|
|||||||
import GameObject = Phaser.GameObjects.GameObject;
|
import GameObject = Phaser.GameObjects.GameObject;
|
||||||
import { Queue } from 'queue-typescript';
|
import { Queue } from 'queue-typescript';
|
||||||
import {SimplePeer} from "../../WebRtc/SimplePeer";
|
import {SimplePeer} from "../../WebRtc/SimplePeer";
|
||||||
|
import {ReconnectingSceneName} from "../Reconnecting/ReconnectingScene";
|
||||||
|
|
||||||
|
|
||||||
export enum Textures {
|
export enum Textures {
|
||||||
@ -123,8 +124,7 @@ export class GameScene extends Phaser.Scene {
|
|||||||
|
|
||||||
this.MapKey = MapKey;
|
this.MapKey = MapKey;
|
||||||
this.MapUrlFile = MapUrlFile;
|
this.MapUrlFile = MapUrlFile;
|
||||||
this.RoomId = this.instance + '__' + this.MapKey;
|
this.RoomId = this.instance + '__' + GameScene.getMapKeyByUrl(MapUrlFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//hook preload scene
|
//hook preload scene
|
||||||
@ -186,11 +186,29 @@ export class GameScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
connection.onServerDisconnected(() => {
|
||||||
|
console.log('Player disconnected from server. Reloading scene.');
|
||||||
|
|
||||||
|
this.simplePeer.closeAllConnections();
|
||||||
|
|
||||||
|
let key = 'somekey'+Math.round(Math.random()*10000);
|
||||||
|
const game : Phaser.Scene = GameScene.createFromUrl(this.MapUrlFile, this.instance, key);
|
||||||
|
this.scene.add(key, game, false,
|
||||||
|
{
|
||||||
|
initPosition: {
|
||||||
|
x: this.CurrentPlayer.x,
|
||||||
|
y: this.CurrentPlayer.y
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.scene.start(key);
|
||||||
|
})
|
||||||
|
|
||||||
// When connection is performed, let's connect SimplePeer
|
// When connection is performed, let's connect SimplePeer
|
||||||
this.simplePeer = new SimplePeer(this.connection);
|
this.simplePeer = new SimplePeer(this.connection);
|
||||||
|
|
||||||
if (this.scene.isPaused()) {
|
if (this.scene.isSleeping()) {
|
||||||
this.scene.resume();
|
this.scene.wake();
|
||||||
|
this.scene.sleep(ReconnectingSceneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
@ -326,7 +344,13 @@ export class GameScene extends Phaser.Scene {
|
|||||||
|
|
||||||
// Let's pause the scene if the connection is not established yet
|
// Let's pause the scene if the connection is not established yet
|
||||||
if (this.connection === undefined) {
|
if (this.connection === undefined) {
|
||||||
this.scene.pause();
|
// Let's wait 0.5 seconds before printing the "connecting" screen to avoid blinking
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.connection === undefined) {
|
||||||
|
this.scene.sleep();
|
||||||
|
this.scene.launch(ReconnectingSceneName);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +209,12 @@ export class SimplePeer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public closeAllConnections() {
|
||||||
|
for (const userId of this.PeerConnectionArray.keys()) {
|
||||||
|
this.closeConnection(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"module": "CommonJS",
|
"module": "CommonJS",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
|
"downlevelIteration": true,
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user