Skip to content

Commit 2abfc7d

Browse files
committed
reconnect: fix socket events
1 parent c0a6e8d commit 2abfc7d

File tree

13 files changed

+184
-109
lines changed

13 files changed

+184
-109
lines changed

Client/scripts/__WarpConfig/__WarpConfig.gml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ network_set_config(network_config_use_non_blocking_socket, true)
1616
// toggle this off if you have some specific case where you need to keep the entities that are in the room locally
1717
#macro PURGE_ENTITIES_ON_ROOM_START true
1818

19-
// instantly teleports if an entity has moved > than this on a single axis in a single tick
19+
// instantly teleports if an entity has moved > than this along an axis in a single tick
2020
#macro POS_INTERP_THRESH 100
2121

2222
#macro TIMESTAMPS_ENABLED true
@@ -79,7 +79,7 @@ if (!CONFIGS_SET) {
7979

8080
#macro SESSION_FILE $"session{MultiClientGetID()}.token"
8181
#macro OLD_SESSIONS_FILE "sessions_old.token"
82-
#macro CONNECT_TIMEOUT 60 * 5 // 5 seconds
82+
//#macro CONNECT_TIMEOUT 60 * 5 // 5 seconds
8383

8484

8585
// Allow up to 4000 ping (YYG recommends ~1000 for LAN-only games)

Client/scripts/authHandlers/authHandlers.gml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ var sessionHandler = function(data) {
6767
trace("Failed to login with a session. Reason: %", data.reason)
6868

6969
// create a new session if the old one didn't work
70-
//sendSessionCreate()
70+
sendSessionCreate()
7171
}
7272
}
7373
}

TypescriptServer/src/cmd/handlers/auth.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { addHandler } from "#cmd/handlePacket";
22
import { Account, getAccountInfo, IAccount } from "#schemas/account";
33
import Session from "#schemas/session";
4-
import { accountCreate, accountLogin, accountRegister, sessionCreate, sessionGet, sessionLogin } from "#util/auth";
4+
import { accountActivate, accountCreate, accountLogin, accountRegister, sessionCreate, sessionGet, sessionLogin } from "#util/auth";
55
import trace from "#util/logging";
66
import { Names } from "#util/names";
77

@@ -30,19 +30,30 @@ addHandler('session create', async (c, data) => {
3030

3131
addHandler('session login', async (c, data) => {
3232
let token = data.session;
33-
trace('session token login: ' + token);
3433

3534
try {
3635
c.session = await sessionGet(token);
3736
c.account = await sessionLogin(c.session);
3837

3938
await c.login(c.account);
40-
c.send({ cmd: 'session login', success: true, session: c.session.token });
39+
c.sendSession(true);
4140
c.sendLogin(true);
41+
42+
// another client logged into the same session?
43+
let old_client = global.clients.find((client) => client !== c && client.session.token === c.session.token);
44+
45+
if (old_client !== undefined) {
46+
if (old_client.connected) {
47+
old_client.disconnect();
48+
}
49+
50+
old_client.reconnect(c);
51+
}
4252
}
4353
catch(reason) {
4454
trace('error: ' + reason.toString());
45-
c.send({ cmd: 'session login', success: false, reason: reason.toString() });
55+
c.sendSession(false, reason);
56+
// c.send({ cmd: 'session login', success: false, reason: reason.toString() });
4657
}
4758
});
4859

@@ -53,9 +64,11 @@ addHandler('login', (c, data) => {
5364

5465
accountLogin(username, password)
5566
.then((account:IAccount) => {
56-
// this also sends the message
5767
c.login(account);
68+
c.session = sessionCreate(account);
69+
5870
c.sendLogin(true);
71+
c.sendSession(true);
5972
})
6073
.catch((reason) => {
6174
c.sendLogin(false, reason);
@@ -66,10 +79,23 @@ addHandler('register', (c, data) => {
6679
let { username, password } = data;
6780
username = username.toLowerCase();
6881

69-
accountRegister(username, password)
82+
let promise: Promise<IAccount>;
83+
84+
if (c.session && c.account && c.account.temporary) {
85+
promise = accountActivate(c.account, username, password);
86+
}
87+
else {
88+
promise = accountRegister(username, password);
89+
}
90+
91+
promise
7092
.then((account:IAccount) => {
7193
c.register(account);
94+
c.session = sessionCreate(c.account);
95+
7296
c.sendRegister(true);
97+
c.sendLogin(true);
98+
c.sendSession(true);
7399
})
74100
.catch((reason) => {
75101
c.sendRegister(false, reason);

TypescriptServer/src/cmd/sendStuff.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ export abstract class SendStuff implements IClient {
3939
abstract halfpack: Buffer;
4040
abstract entity: PlayerEntity;
4141

42+
abstract bindTCP(socket: net.Socket): void;
43+
abstract bindWS(socket: WebSocket): void;
44+
4245

4346
abstract ping: number;
4447

TypescriptServer/src/cmd/senders/auth.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ declare module "#cmd/sendStuff" {
88
sendName()
99
sendRegister(success:boolean, reason?:string)
1010
sendLogin(success:boolean, reason?:string)
11-
sendSession(session_token:string)
11+
sendSession(success:boolean, reason?:string, session_token?:string)
1212
}
1313
}
1414

@@ -30,4 +30,11 @@ SendStuff.prototype.sendRegister = function(success:boolean, reason:string = '')
3030
*/
3131
SendStuff.prototype.sendLogin = function(success:boolean, reason:string = ''):void {
3232
this.send({ cmd: 'login', success, reason, account: getAccountInfo(this.account), profile: getProfileInfo(this.profile) });
33+
}
34+
35+
SendStuff.prototype.sendSession = function(success, reason:string = '', token = undefined) {
36+
if (token === undefined && success) {
37+
token = this.session.token;
38+
}
39+
this.send({ cmd: 'session login', success, reason, session: token });
3340
}

TypescriptServer/src/concepts/client.ts

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,20 @@ export default class Client extends SendStuff implements IClient {
7272
// used internally in packet.ts
7373
/** @type {Buffer} */
7474
halfpack: Buffer;
75-
7675
/** @type {any[]} */
7776
packetQueue: any[];
7877

78+
// used internally in server.ts
79+
bindTCP;
80+
bindWS;
81+
7982
/** @type {PlayerEntity} */
8083
entity: PlayerEntity = null;
8184

8285
/** @type {number} */
8386
ping: number;
8487

85-
room_join_timer: number = -1; // if >0 - joined a room recently
88+
room_join_timer: number = -1; // if >0 - joined a room recently, getting FULL entities list
8689
reconnect_timer: number = -1;
8790

8891
/** @type {boolean} */
@@ -231,21 +234,14 @@ export default class Client extends SendStuff implements IClient {
231234
}
232235
}
233236

234-
disconnect() {
235-
if (this.socket_type === 'ws') {
236-
(this.socket as WebSocket).close();
237-
}
238-
else {
239-
(this.socket as TCPSocket).destroy();
240-
}
241-
}
242-
243237
onDisconnect() {
244238
this.socket = null;
245239
this.connected = false;
246240

247241
this.reconnect_timer = config.reconnect_timeout;
248242

243+
this.matchMakingStop();
244+
249245
// go offline
250246
if (this.logged_in) {
251247
this.profile.online = false;
@@ -254,6 +250,29 @@ export default class Client extends SendStuff implements IClient {
254250
}
255251
}
256252

253+
onReconnect() {
254+
if (this.lobby)
255+
this.sendLobbyJoin(this.lobby);
256+
if (this.room && this.entity)
257+
this.sendPlay(this.lobby, this.room, this.entity.pos, this.entity.uuid);
258+
259+
this.room_join_timer = global.config.room.recently_joined_timer;
260+
}
261+
262+
263+
disconnect() {
264+
if (this.socket === null) {
265+
return;
266+
}
267+
268+
if (this.socket_type === 'ws') {
269+
(this.socket as WebSocket).close();
270+
}
271+
else {
272+
(this.socket as TCPSocket).destroy();
273+
}
274+
}
275+
257276
destroy() {
258277
// save everything to the DB
259278
this.save();
@@ -267,31 +286,38 @@ export default class Client extends SendStuff implements IClient {
267286
this.party.kickMember(this, 'disconnect', true);
268287

269288

270-
global.clients.splice(global.clients.indexOf(this), 1);
289+
let idx = global.clients.indexOf(this);
290+
if (idx != -1)
291+
global.clients.splice(idx, 1);
271292

272293
this.disconnect();
273294
}
274295

275-
// insert this socket into a "dead" (disconnected) client
276-
replace(old_client: Client) {
277-
if (old_client.connected) {
278-
return null;
296+
// move a new client's socket into this "dead" (disconnected) client
297+
// removes the other client from the global.clients list
298+
reconnect(new_client: Client) {
299+
if (this.connected) {
300+
return;
279301
}
280302

281-
old_client.socket = this.socket;
282-
old_client.socket_type = this.socket_type;
303+
this.connected = true;
283304

284-
// delete self from the list
285-
global.clients.splice(global.clients.indexOf(this), 1);
305+
this.socket = new_client.socket;
306+
this.socket_type = new_client.socket_type;
286307

287-
return old_client;
288-
}
308+
this.socket.removeAllListeners();
309+
310+
if (this.socket_type === 'tcp')
311+
this.bindTCP(this.socket);
312+
else
313+
this.bindWS(this.socket);
289314

290-
onReconnect() {
291-
if (this.lobby)
292-
this.sendLobbyJoin(this.lobby);
293-
if (this.room && this.entity)
294-
this.sendPlay(this.lobby, this.room, this.entity.pos, this.entity.uuid);
315+
// delete self from the list
316+
let idx = global.clients.indexOf(new_client);
317+
if (idx != -1)
318+
global.clients.splice(idx, 1);
319+
320+
this.onReconnect();
295321
}
296322

297323

@@ -517,7 +543,7 @@ export default class Client extends SendStuff implements IClient {
517543
}
518544

519545
matchMakingStart(req:MatchRequirements):Ticket|string {
520-
if (this.ticket) return 'already matchmaking';
546+
if (this.ticket !== null) return 'already matchmaking';
521547
if (this.match) return 'already in a match';
522548

523549
if (this.party) {
@@ -554,9 +580,9 @@ export default class Client extends SendStuff implements IClient {
554580
/**
555581
* Save account and profile data to the DB
556582
*/
557-
save() {
583+
async save() {
558584
if (this.account !== null) {
559-
this.account.save()
585+
await this.account.save()
560586
.then(() => {
561587
// trace('Saved the account successfully');
562588
})
@@ -570,7 +596,7 @@ export default class Client extends SendStuff implements IClient {
570596
this.profile.state.lobbyid = this.lobby.lobbyid;
571597
}
572598

573-
this.profile.save()
599+
await this.profile.save()
574600
.then(() => {
575601
// trace('Saved the profile successfully.');
576602
})
@@ -579,7 +605,7 @@ export default class Client extends SendStuff implements IClient {
579605
});
580606
}
581607
if (this.session !== null) {
582-
this.session.save()
608+
await this.session.save()
583609
.then(() => {
584610
// trace('Saved the session successfully');
585611
})

TypescriptServer/src/concepts/room.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,10 @@ class Room extends EventEmitter {
184184
let full_bundle = { cmd: 'entities', room: this.level.room_name, full: true, entities: this.full_bundle };
185185

186186
this.players.forEach(player => {
187-
// we will send everything every frame to those who joined recently (so that they 100% get it)
187+
// we will send ALL the entities data every frame to those who joined recently (so that they 100% get it)
188188
if (player.room_join_timer > 0) {
189189
player.send(full_bundle);
190-
player.room_join_timer--;
190+
player.room_join_timer -= 1 / this.tickrate;
191191
}
192192
// broadcast the min bundle (only changed entities) to everyone else
193193
else if (this.bundle.length > 0)
@@ -282,7 +282,7 @@ class Room extends EventEmitter {
282282
player.entity = player_entity;
283283
}
284284
// add to the recently joined list to receive the old entities
285-
player.room_join_timer = global.config.room.recently_joined_timer * global.config.tps;
285+
player.room_join_timer = global.config.room.recently_joined_timer;
286286

287287
this.emit('player join', player);
288288
}

TypescriptServer/src/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ const common_config = {
112112
// set to -1 to disable this feature
113113
// (!!! setting to 0 might cause problems and unexpected behaviour !!!)
114114

115-
recently_joined_timer: 2 // (seconds) - time
115+
recently_joined_timer: 2 // (seconds) - time after a client joins to receive ALL entity data
116116
},
117117

118118
party: {
@@ -163,7 +163,7 @@ const common_config = {
163163
necessary_login: false, // if true, won't allow a client to join any lobby before logging in
164164

165165
ping_interval: 5 * 1000,
166-
reconnect_timeout: 10 * 1000 // keep a "dead" client in all the lobbies after socket disconnecting, waiting to reconnect with the same account
166+
reconnect_timeout: 15 * 1000 // keep a "dead" client in all the lobbies after socket disconnecting, waiting to reconnect with the same account
167167
}
168168

169169
const prod_config = {

TypescriptServer/src/initializers/08_ping.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ const ping_interval = setInterval(() => {
22
global.clients.forEach((c) => {
33
c.sendPing();
44

5-
if (c.reconnect_timer < 0) {
6-
5+
if (!c.connected) {
6+
c.reconnect_timer -= global.config.ping_interval;
7+
if (c.reconnect_timer < 0) {
8+
c.destroy();
9+
}
710
}
811
})
912
}, global.config.ping_interval);

0 commit comments

Comments
 (0)