diff --git a/pusher/src/Controller/IoSocketController.ts b/pusher/src/Controller/IoSocketController.ts index e526b47e..bd9b5821 100644 --- a/pusher/src/Controller/IoSocketController.ts +++ b/pusher/src/Controller/IoSocketController.ts @@ -22,13 +22,14 @@ import { UserMovesMessage } from "../Messages/generated/messages_pb"; import { TemplatedApp } from "uWebSockets.js"; import { parse } from "query-string"; import { jwtTokenManager } from "../Services/JWTTokenManager"; -import { adminApi, CharacterTexture, FetchMemberDataByUuidResponse } from "../Services/AdminApi"; +import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi"; import { SocketManager, socketManager } from "../Services/SocketManager"; import { emitInBatch } from "../Services/IoSocketHelpers"; import { ADMIN_API_TOKEN, ADMIN_API_URL, SOCKET_IDLE_TIMER } from "../Enum/EnvironmentVariable"; import { Zone } from "_Model/Zone"; import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface"; import { v4 } from "uuid"; +import { CharacterTexture } from "../Services/AdminApi/CharacterTexture"; export class IoSocketController { private nextUserId: number = 1; diff --git a/pusher/src/Controller/MapController.ts b/pusher/src/Controller/MapController.ts index b7643fee..6ea2f19d 100644 --- a/pusher/src/Controller/MapController.ts +++ b/pusher/src/Controller/MapController.ts @@ -1,9 +1,10 @@ import { HttpRequest, HttpResponse, TemplatedApp } from "uWebSockets.js"; import { BaseController } from "./BaseController"; import { parse } from "query-string"; -import { adminApi, MapDetailsData } from "../Services/AdminApi"; +import { adminApi } from "../Services/AdminApi"; import { ADMIN_API_URL } from "../Enum/EnvironmentVariable"; import { GameRoomPolicyTypes } from "../Model/PusherRoom"; +import { MapDetailsData } from "../Services/AdminApi/MapDetailsData"; export class MapController extends BaseController { constructor(private App: TemplatedApp) { @@ -57,6 +58,7 @@ export class MapController extends BaseController { policy_type: GameRoomPolicyTypes.ANONYMOUS_POLICY, roomSlug: "", // Deprecated tags: [], + textures: [], } as MapDetailsData) ); diff --git a/pusher/src/Model/Websocket/ExAdminSocketInterface.ts b/pusher/src/Model/Websocket/ExAdminSocketInterface.ts index 7599c82c..572bd0fe 100644 --- a/pusher/src/Model/Websocket/ExAdminSocketInterface.ts +++ b/pusher/src/Model/Websocket/ExAdminSocketInterface.ts @@ -10,7 +10,6 @@ import { SubMessage, } from "../../Messages/generated/messages_pb"; import { WebSocket } from "uWebSockets.js"; -import { CharacterTexture } from "../../Services/AdminApi"; import { ClientDuplexStream } from "grpc"; import { Zone } from "_Model/Zone"; diff --git a/pusher/src/Model/Websocket/ExSocketInterface.ts b/pusher/src/Model/Websocket/ExSocketInterface.ts index 9a92a0e7..ff5ed211 100644 --- a/pusher/src/Model/Websocket/ExSocketInterface.ts +++ b/pusher/src/Model/Websocket/ExSocketInterface.ts @@ -9,9 +9,9 @@ import { SubMessage, } from "../../Messages/generated/messages_pb"; import { WebSocket } from "uWebSockets.js"; -import { CharacterTexture } from "../../Services/AdminApi"; import { ClientDuplexStream } from "grpc"; import { Zone } from "_Model/Zone"; +import { CharacterTexture } from "../../Services/AdminApi/CharacterTexture"; export type BackConnection = ClientDuplexStream; diff --git a/pusher/src/Services/AdminApi.ts b/pusher/src/Services/AdminApi.ts index 5a3abef2..30fa8e5d 100644 --- a/pusher/src/Services/AdminApi.ts +++ b/pusher/src/Services/AdminApi.ts @@ -1,6 +1,9 @@ import { ADMIN_API_TOKEN, ADMIN_API_URL } from "../Enum/EnvironmentVariable"; import Axios from "axios"; import { GameRoomPolicyTypes } from "_Model/PusherRoom"; +import { CharacterTexture } from "./AdminApi/CharacterTexture"; +import { MapDetailsData } from "./AdminApi/MapDetailsData"; +import { RoomRedirect } from "./AdminApi/RoomRedirect"; export interface AdminApiData { roomUrl: string; @@ -12,25 +15,11 @@ export interface AdminApiData { textures: CharacterTexture[]; } -export interface MapDetailsData { - roomSlug: string; - mapUrl: string; - policy_type: GameRoomPolicyTypes; - tags: string[]; -} - export interface AdminBannedData { is_banned: boolean; message: string; } -export interface CharacterTexture { - id: number; - level: number; - url: string; - rights: string; -} - export interface FetchMemberDataByUuidResponse { uuid: string; tags: string[]; @@ -41,7 +30,7 @@ export interface FetchMemberDataByUuidResponse { } class AdminApi { - async fetchMapDetails(playUri: string): Promise { + async fetchMapDetails(playUri: string): Promise { if (!ADMIN_API_URL) { return Promise.reject(new Error("No admin backoffice set!")); } diff --git a/pusher/src/Services/AdminApi/CharacterTexture.ts b/pusher/src/Services/AdminApi/CharacterTexture.ts new file mode 100644 index 00000000..055b3033 --- /dev/null +++ b/pusher/src/Services/AdminApi/CharacterTexture.ts @@ -0,0 +1,11 @@ +import * as tg from "generic-type-guard"; + +export const isCharacterTexture = new tg.IsInterface() + .withProperties({ + id: tg.isNumber, + level: tg.isNumber, + url: tg.isString, + rights: tg.isString, + }) + .get(); +export type CharacterTexture = tg.GuardedType; diff --git a/pusher/src/Services/AdminApi/MapDetailsData.ts b/pusher/src/Services/AdminApi/MapDetailsData.ts new file mode 100644 index 00000000..bf711799 --- /dev/null +++ b/pusher/src/Services/AdminApi/MapDetailsData.ts @@ -0,0 +1,20 @@ +import * as tg from "generic-type-guard"; +import { GameRoomPolicyTypes } from "_Model/PusherRoom"; +import { isCharacterTexture } from "./CharacterTexture"; +import { isAny, isNumber } from "generic-type-guard"; + +/*const isNumericEnum = + (vs: T) => + (v: any): v is T => + typeof v === "number" && v in vs;*/ + +export const isMapDetailsData = new tg.IsInterface() + .withProperties({ + roomSlug: tg.isOptional(tg.isString), // deprecated + mapUrl: tg.isString, + policy_type: isNumber, //isNumericEnum(GameRoomPolicyTypes), + tags: tg.isArray(tg.isString), + textures: tg.isArray(isCharacterTexture), + }) + .get(); +export type MapDetailsData = tg.GuardedType; diff --git a/pusher/src/Services/AdminApi/RoomRedirect.ts b/pusher/src/Services/AdminApi/RoomRedirect.ts new file mode 100644 index 00000000..7257ebd3 --- /dev/null +++ b/pusher/src/Services/AdminApi/RoomRedirect.ts @@ -0,0 +1,8 @@ +import * as tg from "generic-type-guard"; + +export const isRoomRedirect = new tg.IsInterface() + .withProperties({ + redirectUrl: tg.isString, + }) + .get(); +export type RoomRedirect = tg.GuardedType; diff --git a/pusher/src/Services/SocketManager.ts b/pusher/src/Services/SocketManager.ts index 8dd8abb9..b8221b8e 100644 --- a/pusher/src/Services/SocketManager.ts +++ b/pusher/src/Services/SocketManager.ts @@ -33,7 +33,7 @@ import { } from "../Messages/generated/messages_pb"; import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils"; import { ADMIN_API_URL, JITSI_ISS, SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable"; -import { adminApi, CharacterTexture } from "./AdminApi"; +import { adminApi } from "./AdminApi"; import { emitInBatch } from "./IoSocketHelpers"; import Jwt from "jsonwebtoken"; import { JITSI_URL } from "../Enum/EnvironmentVariable"; @@ -44,6 +44,8 @@ import { GroupDescriptor, UserDescriptor, ZoneEventListener } from "_Model/Zone" import Debug from "debug"; import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface"; import { WebSocket } from "uWebSockets.js"; +import { isRoomRedirect } from "./AdminApi/RoomRedirect"; +import { CharacterTexture } from "./AdminApi/CharacterTexture"; const debug = Debug("socket"); @@ -374,8 +376,14 @@ export class SocketManager implements ZoneEventListener { public async updateRoomWithAdminData(room: PusherRoom): Promise { const data = await adminApi.fetchMapDetails(room.roomUrl); - room.tags = data.tags; - room.policyType = Number(data.policy_type); + + if (isRoomRedirect(data)) { + // TODO: if the updated room data is actually a redirect, we need to take everybody on the map + // and redirect everybody to the new location (so we need to close the connection for everybody) + } else { + room.tags = data.tags; + room.policyType = Number(data.policy_type); + } } emitPlayGlobalMessage(client: ExSocketInterface, playglobalmessage: PlayGlobalMessage) {