Refactoring messages
[libreadventure.git] / front / src / Connexion.ts
1 import {GameManager} from "./Phaser/Game/GameManager";
2
3 const SocketIo = require('socket.io-client');
4 import Axios from "axios";
5 import {API_URL} from "./Enum/EnvironmentVariable";
6 import {getMapKeyByUrl} from "./Phaser/Login/LogincScene";
7 import {MessageUI} from "./Logger/MessageUI";
8
9 enum EventMessage{
10 WEBRTC_SIGNAL = "webrtc-signal",
11 WEBRTC_START = "webrtc-start",
12 WEBRTC_JOIN_ROOM = "webrtc-join-room",
13 JOIN_ROOM = "join-room",
14 USER_POSITION = "user-position",
15 MESSAGE_ERROR = "message-error",
16 WEBRTC_DISCONNECT = "webrtc-disconect",
17 GROUP_CREATE_UPDATE = "group-create-update",
18 GROUP_DELETE = "group-delete",
19
20 CONNECT_ERROR = "connect_error",
21 RECONNECT = "reconnect",
22 ATTRIBUTE_USER_ID = "attribute-user-id" // Sent from server to client just after the connexion is established to give the client its unique id.
23 }
24
25 class Message {
26 userId: string;
27 roomId: string;
28 name: string;
29 character: string;
30
31 constructor(userId : string, roomId : string, name: string, character: string) {
32 this.userId = userId;
33 this.roomId = roomId;
34 this.name = name;
35 this.character = character;
36 }
37 }
38
39 export interface PointInterface {
40 x: number;
41 y: number;
42 direction : string;
43 }
44
45 class Point implements PointInterface{
46 x: number;
47 y: number;
48 direction : string;
49
50 constructor(x : number, y : number, direction : string = "none") {
51 if(x === null || y === null){
52 throw Error("position x and y cannot be null");
53 }
54 this.x = x;
55 this.y = y;
56 this.direction = direction;
57 }
58 }
59
60 export interface MessageUserPositionInterface {
61 userId: string;
62 roomId: string;
63 name: string;
64 character: string;
65 position: PointInterface;
66 }
67
68 class MessageUserPosition extends Message implements MessageUserPositionInterface{
69 position: PointInterface;
70
71 constructor(userId : string, roomId : string, point : Point, name: string, character: string) {
72 super(userId, roomId, name, character);
73 this.position = point;
74 }
75 }
76
77 export interface ListMessageUserPositionInterface {
78 roomId: string;
79 listUsersPosition: Array<MessageUserPosition>;
80 }
81
82 class ListMessageUserPosition {
83 roomId: string;
84 listUsersPosition: Array<MessageUserPosition>;
85
86 constructor(roomId: string, data: any) {
87 this.roomId = roomId;
88 this.listUsersPosition = new Array<MessageUserPosition>();
89 data.forEach((userPosition: any) => {
90 this.listUsersPosition.push(new MessageUserPosition(
91 userPosition.userId,
92 userPosition.roomId,
93 new Point(
94 userPosition.position.x,
95 userPosition.position.y,
96 userPosition.position.direction
97 ),
98 userPosition.name,
99 userPosition.character
100 ));
101 });
102 }
103 }
104
105 export interface PositionInterface {
106 x: number,
107 y: number
108 }
109
110 export interface GroupCreatedUpdatedMessageInterface {
111 position: PositionInterface,
112 groupId: string
113 }
114
115 export interface ConnexionInterface {
116 socket: any;
117 token: string;
118 email: string;
119 userId: string;
120
121 createConnexion(characterSelected: string): Promise<any>;
122
123 loadMaps(): Promise<any>;
124
125 joinARoom(roomId: string, character: string): void;
126
127 sharePosition(x: number, y: number, direction: string, roomId: string, character: string): void;
128
129 positionOfAllUser(): void;
130
131 /*webrtc*/
132 sendWebrtcSignal(signal: any, roomId: string, userId?: string, receiverId?: string): void;
133
134 receiveWebrtcSignal(callBack: Function): void;
135
136 receiveWebrtcStart(callBack: Function): void;
137
138 disconnectMessage(callBack: Function): void;
139 }
140
141 export class Connexion implements ConnexionInterface {
142 socket: any;
143 token: string;
144 email: string;
145 userId: string;
146
147 GameManager: GameManager;
148
149 lastPositionShared: MessageUserPosition = null;
150
151 constructor(email : string, GameManager: GameManager) {
152 this.email = email;
153 this.GameManager = GameManager;
154 }
155
156 /**
157 * @param characterSelected
158 */
159 createConnexion(characterSelected: string): Promise<ConnexionInterface> {
160 /*return Axios.post(`${API_URL}/login`, {email: this.email})
161 .then((res) => {
162 this.token = res.data.token;
163 this.userId = res.data.userId;*/
164
165 this.socket = SocketIo(`${API_URL}`, {
166 /*query: {
167 token: this.token
168 }*/
169 });
170
171 this.connectSocketServer();
172
173 // TODO: maybe trigger promise only when connexion is established?
174 let promise = new Promise<ConnexionInterface>((resolve, reject) => {
175 /*console.log('PROMISE CREATED')
176 this.socket.on('connection', () => {
177 console.log('CONNECTED');
178 resolve(this);
179 });*/
180 resolve(this);
181 });
182
183 return promise;
184
185 /* return res.data;
186 })
187 .catch((err) => {
188 console.error(err);
189 throw err;
190 });*/
191 }
192
193 /**
194 *
195 * @param character
196 */
197 connectSocketServer(character : string = null){
198 //if try to reconnect with last position
199 if(this.lastPositionShared) {
200 //join the room
201 this.joinARoom(
202 this.lastPositionShared.roomId,
203 this.lastPositionShared.character
204 );
205
206 //share your first position
207 this.sharePosition(
208 this.lastPositionShared ? this.lastPositionShared.position.x : 0,
209 this.lastPositionShared ? this.lastPositionShared.position.y : 0,
210 this.lastPositionShared.character,
211 this.lastPositionShared.roomId,
212 this.lastPositionShared.position.direction
213 );
214 }
215
216 //listen event
217 this.attributeUserId();
218 this.positionOfAllUser();
219 this.disconnectServer();
220 this.errorMessage();
221 this.groupUpdatedOrCreated();
222 this.groupDeleted();
223 }
224
225 //TODO add middleware with access token to secure api
226 loadMaps() : Promise<any> {
227 return Axios.get(`${API_URL}/maps`)
228 .then((res) => {
229 return res.data;
230 }).catch((err) => {
231 console.error(err);
232 throw err;
233 });
234 }
235
236 /**
237 *
238 * @param roomId
239 * @param character
240 */
241 joinARoom(roomId: string, character: string): void {
242 let messageUserPosition = new MessageUserPosition(
243 this.userId,
244 roomId,
245 new Point(0, 0),
246 this.email,
247 character
248 );
249 this.socket.emit(EventMessage.JOIN_ROOM, messageUserPosition);
250 }
251
252 /**
253 *
254 * @param x
255 * @param y
256 * @param character
257 * @param roomId
258 * @param direction
259 */
260 sharePosition(x : number, y : number, character : string, roomId : string, direction : string = "none") : void{
261 if(!this.socket){
262 return;
263 }
264 let messageUserPosition = new MessageUserPosition(
265 this.userId,
266 roomId,
267 new Point(x, y, direction),
268 this.email,
269 character
270 );
271 this.lastPositionShared = messageUserPosition;
272 this.socket.emit(EventMessage.USER_POSITION, messageUserPosition);
273 }
274
275 attributeUserId(): void {
276 // This event is received as soon as the connexion is established.
277 // It allows informing the browser of its own user id.
278 this.socket.on(EventMessage.ATTRIBUTE_USER_ID, (userId: string) => {
279 console.log('Received my user id: ', userId);
280 this.userId = userId;
281 });
282 }
283
284 /**
285 * The data sent is an array with information for each user :
286 * [
287 * {
288 * userId: <string>,
289 * roomId: <string>,
290 * position: {
291 * x : <number>,
292 * y : <number>,
293 * direction: <string>
294 * }
295 * },
296 * ...
297 * ]
298 **/
299 positionOfAllUser(): void {
300 this.socket.on(EventMessage.USER_POSITION, (message: string) => {
301 let dataList = message;
302 let UserPositions : Array<any> = Object.values(dataList);
303 let listMessageUserPosition = new ListMessageUserPosition(UserPositions[0], UserPositions[1]);
304 this.GameManager.shareUserPosition(listMessageUserPosition);
305 });
306 }
307
308 private groupUpdatedOrCreated(): void {
309 this.socket.on(EventMessage.GROUP_CREATE_UPDATE, (groupCreateUpdateMessage: GroupCreatedUpdatedMessageInterface) => {
310 //console.log('Group ', groupCreateUpdateMessage.groupId, " position :", groupCreateUpdateMessage.position.x, groupCreateUpdateMessage.position.y)
311 this.GameManager.shareGroupPosition(groupCreateUpdateMessage);
312 })
313 }
314
315 private groupDeleted(): void {
316 this.socket.on(EventMessage.GROUP_DELETE, (groupId: string) => {
317 this.GameManager.deleteGroup(groupId);
318 })
319 }
320
321 sendWebrtcSignal(signal: any, roomId: string, userId? : string, receiverId? : string) {
322 return this.socket.emit(EventMessage.WEBRTC_SIGNAL, {
323 userId: userId ? userId : this.userId,
324 receiverId: receiverId ? receiverId : this.userId,
325 roomId: roomId,
326 signal: signal
327 });
328 }
329
330 receiveWebrtcStart(callback: Function) {
331 this.socket.on(EventMessage.WEBRTC_START, callback);
332 }
333
334 receiveWebrtcSignal(callback: Function) {
335 return this.socket.on(EventMessage.WEBRTC_SIGNAL, callback);
336 }
337
338 errorMessage(): void {
339 this.socket.on(EventMessage.MESSAGE_ERROR, (message: string) => {
340 console.error(EventMessage.MESSAGE_ERROR, message);
341 })
342 }
343
344 disconnectServer(): void {
345 this.socket.on(EventMessage.CONNECT_ERROR, () => {
346 MessageUI.warningMessage("Trying to connect!");
347 });
348
349 this.socket.on(EventMessage.RECONNECT, () => {
350 MessageUI.removeMessage();
351 this.connectSocketServer();
352 });
353 }
354
355 disconnectMessage(callback: Function): void {
356 this.socket.on(EventMessage.WEBRTC_DISCONNECT, callback);
357 }
358 }