🆕 Disconnection handler, when you got disconnected you automatic go back to the room

This commit is contained in:
duckietm
2026-03-19 15:04:47 +01:00
parent eee289e8f2
commit 5aef7a3de2
16 changed files with 498 additions and 87 deletions
+220 -3
View File
@@ -1,22 +1,49 @@
import { IRoomHandlerListener, IRoomSession, IRoomSessionManager } from '@nitrots/api';
import { GetCommunication } from '@nitrots/communication';
import { GetEventDispatcher, RoomSessionEvent } from '@nitrots/events';
import { GetEventDispatcher, NitroEventType, RoomSessionEvent } from '@nitrots/events';
import { NitroLogger } from '@nitrots/utils';
import { RoomSession } from './RoomSession';
import { BaseHandler, GenericErrorHandler, PetPackageHandler, PollHandler, RoomChatHandler, RoomDataHandler, RoomDimmerPresetsHandler, RoomPermissionsHandler, RoomPresentHandler, RoomSessionHandler, RoomUsersHandler, WordQuizHandler } from './handler';
const STORAGE_KEY_ROOM_ID = 'nitro.session.lastRoomId';
const STORAGE_KEY_ROOM_PASSWORD = 'nitro.session.lastRoomPassword';
export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerListener
{
private _handlers: BaseHandler[] = [];
private _sessions: Map<string, IRoomSession> = new Map();
private _pendingSession: IRoomSession = null;
private _sessionStarting: boolean = false;
private _viewerSession: IRoomSession = null;
private _lastRoomId: number = -1;
private _lastRoomPassword: string = null;
private _isReconnecting: boolean = false;
private _reconnectGuardTimer: ReturnType<typeof setTimeout> = null;
public async init(): Promise<void>
{
this.createHandlers();
this.processPendingSession();
this.setupReconnectListener();
this.checkPersistedRoom();
}
private checkPersistedRoom(): void
{
try
{
const storedRoomId = sessionStorage.getItem(STORAGE_KEY_ROOM_ID);
if(!storedRoomId) return;
const roomId = parseInt(storedRoomId, 10);
if(isNaN(roomId) || roomId <= 0) return;
this._lastRoomId = roomId;
this._lastRoomPassword = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null;
this._isReconnecting = true;
}
catch(e) {}
}
private createHandlers(): void
@@ -40,6 +67,158 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList
);
}
private setupReconnectListener(): void
{
GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTING, () =>
{
this._isReconnecting = true;
});
GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECTED, () =>
{
this.clearGuardTimer();
this._reconnectGuardTimer = setTimeout(() =>
{
this._reconnectGuardTimer = null;
if(!this._isReconnecting) return;
this.attemptRoomReEntry();
}, 5000);
});
GetEventDispatcher().addEventListener(NitroEventType.SOCKET_REAUTHENTICATED, () =>
{
this.clearGuardTimer();
this.attemptRoomReEntry();
});
GetEventDispatcher().addEventListener(NitroEventType.SOCKET_RECONNECT_FAILED, () =>
{
this.clearGuardTimer();
this._isReconnecting = false;
this._lastRoomId = -1;
this._lastRoomPassword = null;
this.clearPersistedRoom();
});
GetEventDispatcher().addEventListener(NitroEventType.SOCKET_CLOSED, () =>
{
this.clearGuardTimer();
this._isReconnecting = false;
this._lastRoomId = -1;
this._lastRoomPassword = null;
this.clearPersistedRoom();
});
}
private clearGuardTimer(): void
{
if(this._reconnectGuardTimer)
{
clearTimeout(this._reconnectGuardTimer);
this._reconnectGuardTimer = null;
}
}
private attemptRoomReEntry(): void
{
const roomId = this._lastRoomId;
const password = this._lastRoomPassword;
if(roomId <= 0)
{
this._isReconnecting = false;
return;
}
this._sessions.clear();
this._viewerSession = null;
this.createSession(roomId, password);
this.clearGuardTimer();
this._reconnectGuardTimer = setTimeout(() =>
{
this._reconnectGuardTimer = null;
if(this._isReconnecting)
{
this._isReconnecting = false;
}
}, 10000);
}
public tryRestoreSession(): boolean
{
try
{
const storedRoomId = sessionStorage.getItem(STORAGE_KEY_ROOM_ID);
if(!storedRoomId) return false;
const roomId = parseInt(storedRoomId, 10);
if(isNaN(roomId) || roomId <= 0) return false;
const password = sessionStorage.getItem(STORAGE_KEY_ROOM_PASSWORD) || null;
this._isReconnecting = true;
this.createSession(roomId, password);
this.clearGuardTimer();
this._reconnectGuardTimer = setTimeout(() =>
{
this._reconnectGuardTimer = null;
if(this._isReconnecting)
{
this._isReconnecting = false;
}
}, 10000);
return true;
}
catch(e)
{
return false;
}
}
private persistRoom(roomId: number, password: string): void
{
try
{
if(roomId > 0)
{
sessionStorage.setItem(STORAGE_KEY_ROOM_ID, roomId.toString());
if(password)
{
sessionStorage.setItem(STORAGE_KEY_ROOM_PASSWORD, password);
}
else
{
sessionStorage.removeItem(STORAGE_KEY_ROOM_PASSWORD);
}
}
else
{
this.clearPersistedRoom();
}
}
catch(e) {}
}
private clearPersistedRoom(): void
{
try
{
sessionStorage.removeItem(STORAGE_KEY_ROOM_ID);
sessionStorage.removeItem(STORAGE_KEY_ROOM_PASSWORD);
}
catch(e) {}
}
private setHandlers(session: IRoomSession): void
{
if(!this._handlers || !this._handlers.length) return;
@@ -92,6 +271,10 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList
this._viewerSession = roomSession;
this._lastRoomId = roomSession.roomId;
this._lastRoomPassword = roomSession.password;
this.persistRoom(roomSession.roomId, roomSession.password);
this.startSession(this._viewerSession);
return true;
@@ -125,6 +308,18 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList
this._sessions.delete(this.getRoomId(id));
if(openLandingView && !this._isReconnecting)
{
this._lastRoomId = -1;
this._lastRoomPassword = null;
this.clearPersistedRoom();
}
if(this._isReconnecting)
{
return;
}
GetEventDispatcher().dispatchEvent(new RoomSessionEvent(RoomSessionEvent.ENDED, session, openLandingView));
}
@@ -132,15 +327,34 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList
{
const session = this.getSession(id);
if(!session) return;
if(!session)
{
return;
}
switch(type)
{
case RoomSessionHandler.RS_CONNECTED:
if(this._isReconnecting)
{
this.clearGuardTimer();
this._isReconnecting = false;
}
return;
case RoomSessionHandler.RS_READY:
if(this._isReconnecting)
{
this.clearGuardTimer();
this._isReconnecting = false;
}
return;
case RoomSessionHandler.RS_DISCONNECTED:
if(this._isReconnecting) return;
this.removeSession(id);
return;
}
@@ -158,6 +372,9 @@ export class RoomSessionManager implements IRoomSessionManager, IRoomHandlerList
this._sessions.set(this.getRoomId(toRoomId), existing);
this._lastRoomId = toRoomId;
this.persistRoom(toRoomId, existing.password);
this.setHandlers(existing);
}
@@ -54,7 +54,7 @@ export class RoomChatHandler extends BaseHandler
if(!parser) return;
GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.giverUserId, '', RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED, SystemChatStyleEnum.GENERIC, [], null, parser.handItemType));
GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, parser.giverUserId, '', RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED, SystemChatStyleEnum.GENERIC, [], parser.handItemType));
}
private onRespectReceivedEvent(event: RespectReceivedEvent): void
@@ -136,7 +136,7 @@ export class RoomChatHandler extends BaseHandler
break;
}
GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, petData.roomIndex, '', chatType, SystemChatStyleEnum.GENERIC, [], null, userRoomIndex));
GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, petData.roomIndex, '', chatType, SystemChatStyleEnum.GENERIC, null, userRoomIndex));
}
private onFloodControlEvent(event: FloodControlEvent): void
@@ -168,6 +168,6 @@ export class RoomChatHandler extends BaseHandler
if(!parser) return;
GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, session.ownRoomIndex, '', RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING, SystemChatStyleEnum.GENERIC, [], null, parser.seconds));
GetEventDispatcher().dispatchEvent(new RoomSessionChatEvent(RoomSessionChatEvent.CHAT_EVENT, session, session.ownRoomIndex, '', RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING, SystemChatStyleEnum.GENERIC, [], parser.seconds));
}
}