From 4fee1ac2069e325769b6019c669403ccef6d5bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 29 Jun 2020 22:10:23 +0200 Subject: [PATCH 1/6] Refactoring World and Group to use Map and Set instead of arrays --- back/src/Model/Group.ts | 44 ++++++++++++----------------------------- back/src/Model/World.ts | 15 +++++++------- back/tsconfig.json | 1 + 3 files changed, 21 insertions(+), 39 deletions(-) diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index ed09b0cd..16cd5ffe 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -7,13 +7,13 @@ export class Group { static readonly MAX_PER_GROUP = 4; private id: string; - private users: UserInterface[]; + private users: Set; private connectCallback: ConnectCallback; private disconnectCallback: DisconnectCallback; constructor(users: UserInterface[], connectCallback: ConnectCallback, disconnectCallback: DisconnectCallback) { - this.users = []; + this.users = new Set(); this.connectCallback = connectCallback; this.disconnectCallback = disconnectCallback; this.id = uuid(); @@ -24,7 +24,7 @@ export class Group { } getUsers(): UserInterface[] { - return this.users; + return Array.from(this.users.values()); } getId() : string{ @@ -42,8 +42,8 @@ export class Group { x += user.position.x; y += user.position.y; }); - x /= this.users.length; - y /= this.users.length; + x /= this.users.size; + y /= this.users.size; return { x, y @@ -51,45 +51,27 @@ export class Group { } isFull(): boolean { - return this.users.length >= Group.MAX_PER_GROUP; + return this.users.size >= Group.MAX_PER_GROUP; } isEmpty(): boolean { - return this.users.length <= 1; + return this.users.size <= 1; } join(user: UserInterface): void { // Broadcast on the right event this.connectCallback(user.id, this); - this.users.push(user); + this.users.add(user); user.group = this; } - isPartOfGroup(user: UserInterface): boolean - { - return this.users.includes(user); - } - - /*removeFromGroup(users: UserInterface[]): void - { - for(let i = 0; i < users.length; i++){ - let user = users[i]; - const index = this.users.indexOf(user, 0); - if (index > -1) { - this.users.splice(index, 1); - } - } - }*/ - leave(user: UserInterface): void { - const index = this.users.indexOf(user, 0); - if (index === -1) { - throw new Error("Could not find user in the group"); + let success = this.users.delete(user); + if (success === false) { + throw new Error("Could not find user "+user.id+" in the group "+this.id); } - - this.users.splice(index, 1); user.group = undefined; // Broadcast on the right event @@ -102,8 +84,8 @@ export class Group { */ destroy(): void { - this.users.forEach((user: UserInterface) => { + for (let user of this.users) { this.leave(user); - }) + } } } diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index 2cb92dd2..e4ce5c32 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -20,7 +20,7 @@ export class World { // Users, sorted by ID private readonly users: Map; - private readonly groups: Group[]; + private readonly groups: Map; private readonly connectCallback: ConnectCallback; private readonly disconnectCallback: DisconnectCallback; @@ -35,7 +35,7 @@ export class World { groupDeletedCallback: GroupDeletedCallback) { this.users = new Map(); - this.groups = []; + this.groups = new Map(); this.connectCallback = connectCallback; this.disconnectCallback = disconnectCallback; this.minDistance = minDistance; @@ -45,7 +45,7 @@ export class World { } public getGroups(): Group[] { - return this.groups; + return Array.from(this.groups.values()); } public getUsers(): Map { @@ -99,7 +99,7 @@ export class World { user, closestUser ], this.connectCallback, this.disconnectCallback); - this.groups.push(group); + this.groups.set(group.getId(), group); } } @@ -132,11 +132,10 @@ export class World { if (group.isEmpty()) { this.groupDeletedCallback(group.getId(), user); group.destroy(); - const index = this.groups.indexOf(group, 0); - if (index === -1) { - throw new Error("Could not find group"); + if (!this.groups.has(group.getId())) { + throw new Error("Could not find group "+group.getId()+" referenced by user "+user.id+" in World."); } - this.groups.splice(index, 1); + this.groups.delete(group.getId()); } else { this.groupUpdatedCallback(group); } diff --git a/back/tsconfig.json b/back/tsconfig.json index 51858b84..397bb8a2 100644 --- a/back/tsconfig.json +++ b/back/tsconfig.json @@ -4,6 +4,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "downlevelIteration": true, "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ From 31846d1640b3285be62dec5973fa465a2ad17348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 29 Jun 2020 22:13:07 +0200 Subject: [PATCH 2/6] Using a Set for groups --- back/src/Model/Group.ts | 4 ++-- back/src/Model/World.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index 16cd5ffe..4c597557 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -68,7 +68,7 @@ export class Group { leave(user: UserInterface): void { - let success = this.users.delete(user); + const success = this.users.delete(user); if (success === false) { throw new Error("Could not find user "+user.id+" in the group "+this.id); } @@ -84,7 +84,7 @@ export class Group { */ destroy(): void { - for (let user of this.users) { + for (const user of this.users) { this.leave(user); } } diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index e4ce5c32..6d4fc205 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -20,7 +20,7 @@ export class World { // Users, sorted by ID private readonly users: Map; - private readonly groups: Map; + private readonly groups: Set; private readonly connectCallback: ConnectCallback; private readonly disconnectCallback: DisconnectCallback; @@ -35,7 +35,7 @@ export class World { groupDeletedCallback: GroupDeletedCallback) { this.users = new Map(); - this.groups = new Map(); + this.groups = new Set(); this.connectCallback = connectCallback; this.disconnectCallback = disconnectCallback; this.minDistance = minDistance; @@ -99,7 +99,7 @@ export class World { user, closestUser ], this.connectCallback, this.disconnectCallback); - this.groups.set(group.getId(), group); + this.groups.add(group); } } @@ -132,10 +132,10 @@ export class World { if (group.isEmpty()) { this.groupDeletedCallback(group.getId(), user); group.destroy(); - if (!this.groups.has(group.getId())) { + if (!this.groups.has(group)) { throw new Error("Could not find group "+group.getId()+" referenced by user "+user.id+" in World."); } - this.groups.delete(group.getId()); + this.groups.delete(group); } else { this.groupUpdatedCallback(group); } From 6412c56fcd0472d9a5e00d0d44ba98456cef7172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 29 Jun 2020 22:56:41 +0200 Subject: [PATCH 3/6] Adding finally clause to make sure Prometheus indicators are ok --- back/src/Controller/IoSocketController.ts | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 2ea25f31..102c03fb 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -295,20 +295,23 @@ export class IoSocketController { leaveRoom(Client : ExSocketInterface){ // leave previous room and world if(Client.roomId){ - Client.to(Client.roomId).emit(SockerIoEvent.USER_LEFT, Client.userId); + try { + Client.to(Client.roomId).emit(SockerIoEvent.USER_LEFT, Client.userId); - //user leave previous world - const world : World|undefined = this.Worlds.get(Client.roomId); - if(world){ - world.leave(Client); - if (world.isEmpty()) { - this.Worlds.delete(Client.roomId); + //user leave previous world + const world: World | undefined = this.Worlds.get(Client.roomId); + if (world) { + world.leave(Client); + if (world.isEmpty()) { + this.Worlds.delete(Client.roomId); + } } + //user leave previous room + Client.leave(Client.roomId); + } finally { + this.nbClientsPerRoomGauge.dec({ host: os.hostname(), room: Client.roomId }); + delete Client.roomId; } - //user leave previous room - Client.leave(Client.roomId); - this.nbClientsPerRoomGauge.dec({ host: os.hostname(), room: Client.roomId }); - delete Client.roomId; } } From 82c57810a2e8c109bd068fe1f82edb271197e3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 29 Jun 2020 23:01:52 +0200 Subject: [PATCH 4/6] Removing host label from Prometheus because it is redundant --- back/src/Controller/IoSocketController.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 102c03fb..edd29e7b 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -48,12 +48,12 @@ export class IoSocketController { this.nbClientsGauge = new Gauge({ name: 'workadventure_nb_sockets', help: 'Number of connected sockets', - labelNames: [ 'host' ] + labelNames: [ ] }); this.nbClientsPerRoomGauge = new Gauge({ name: 'workadventure_nb_clients_per_room', help: 'Number of clients per room', - labelNames: [ 'host', 'room' ] + labelNames: [ 'room' ] }); // Authentication with token. it will be decoded and stored in the socket. @@ -139,7 +139,7 @@ export class IoSocketController { // Let's log server load when a user joins const srvSockets = this.Io.sockets.sockets; - this.nbClientsGauge.inc({ host: os.hostname() }); + this.nbClientsGauge.inc(); console.log(new Date().toISOString() + ' A user joined (', Object.keys(srvSockets).length, ' connected users)'); si.currentLoad().then(data => console.log(' Current load: ', data.avgload)); si.currentLoad().then(data => console.log(' CPU: ', data.currentload, '%')); @@ -262,7 +262,7 @@ export class IoSocketController { // Let's log server load when a user leaves const srvSockets = this.Io.sockets.sockets; - this.nbClientsGauge.dec({ host: os.hostname() }); + this.nbClientsGauge.dec(); console.log('A user left (', Object.keys(srvSockets).length, ' connected users)'); si.currentLoad().then(data => console.log('Current load: ', data.avgload)); si.currentLoad().then(data => console.log('CPU: ', data.currentload, '%')); @@ -309,7 +309,7 @@ export class IoSocketController { //user leave previous room Client.leave(Client.roomId); } finally { - this.nbClientsPerRoomGauge.dec({ host: os.hostname(), room: Client.roomId }); + this.nbClientsPerRoomGauge.dec({ room: Client.roomId }); delete Client.roomId; } } @@ -318,7 +318,7 @@ export class IoSocketController { private joinRoom(Client : ExSocketInterface, roomId: string, position: PointInterface): World { //join user in room Client.join(roomId); - this.nbClientsPerRoomGauge.inc({ host: os.hostname(), room: roomId }); + this.nbClientsPerRoomGauge.inc({ room: roomId }); Client.roomId = roomId; Client.position = position; From 2b5d3e00172689a7c6c3529af992b03405de8f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 2 Jul 2020 10:18:47 +0200 Subject: [PATCH 5/6] Sending the source map out of the main JS file to reduce size --- front/package.json | 5 +++-- front/webpack.prod.js | 7 +++++++ front/yarn.lock | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 front/webpack.prod.js diff --git a/front/package.json b/front/package.json index d73eb50d..b0c5502b 100644 --- a/front/package.json +++ b/front/package.json @@ -15,7 +15,8 @@ "typescript": "^3.8.3", "webpack": "^4.42.1", "webpack-cli": "^3.3.11", - "webpack-dev-server": "^3.10.3" + "webpack-dev-server": "^3.10.3", + "webpack-merge": "^4.2.2" }, "dependencies": { "@types/axios": "^0.14.0", @@ -28,7 +29,7 @@ }, "scripts": { "start": "webpack-dev-server --open", - "build": "webpack", + "build": "webpack --config webpack.prod.js", "test": "ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json", "lint": "node_modules/.bin/eslint src/ . --ext .ts", "fix": "node_modules/.bin/eslint --fix src/ . --ext .ts" diff --git a/front/webpack.prod.js b/front/webpack.prod.js new file mode 100644 index 00000000..b5695cc6 --- /dev/null +++ b/front/webpack.prod.js @@ -0,0 +1,7 @@ +const merge = require('webpack-merge'); +const common = require('./webpack.config.js'); + +module.exports = merge(common, { + mode: 'production', + devtool: 'source-map' +}); diff --git a/front/yarn.lock b/front/yarn.lock index 126536e0..05e9b368 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -4494,6 +4494,13 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" +webpack-merge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== + dependencies: + lodash "^4.17.15" + webpack-sources@^1.4.0, webpack-sources@^1.4.1: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" From 67e07c04f84ae35f0d9c07964723682f90fe624e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Sun, 5 Jul 2020 17:10:08 +0200 Subject: [PATCH 6/6] Fixing loading of tilesets with margin or padding --- front/src/Phaser/Game/GameScene.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 44c4feb6..cbf5ec26 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -247,7 +247,7 @@ export class GameScene extends Phaser.Scene { //initalise map this.Map = this.add.tilemap(this.MapKey); this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => { - this.Terrains.push(this.Map.addTilesetImage(tileset.name, tileset.name)); + this.Terrains.push(this.Map.addTilesetImage(tileset.name, tileset.name, tileset.tilewidth, tileset.tileheight, tileset.margin, tileset.spacing/*, tileset.firstgid*/)); }); //permit to set bound collision