From c711f6422d7f6ecedc3ddcaf738d04b5f82f5771 Mon Sep 17 00:00:00 2001 From: Archangel Date: Wed, 19 Feb 2025 20:19:42 +0100 Subject: [PATCH] Add backend for headless dropdown --- src/callbacks/FikaRaidCallbacks.ts | 6 +-- src/controllers/FikaRaidController.ts | 16 +++--- src/helpers/FikaHeadlessHelper.ts | 51 +++++++++++++++---- .../headless/IHeadlessAvailableClients.ts | 6 +++ .../headless/IGetStatusHeadlessResponse.ts | 3 -- .../raid/headless/IStartHeadlessRequest.ts | 1 + src/routers/static/FikaRaidStaticRouter.ts | 4 +- src/services/headless/FikaHeadlessService.ts | 14 ++--- 8 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 src/models/fika/headless/IHeadlessAvailableClients.ts delete mode 100644 src/models/fika/routes/raid/headless/IGetStatusHeadlessResponse.ts diff --git a/src/callbacks/FikaRaidCallbacks.ts b/src/callbacks/FikaRaidCallbacks.ts index e5520e71..2c03ad86 100644 --- a/src/callbacks/FikaRaidCallbacks.ts +++ b/src/callbacks/FikaRaidCallbacks.ts @@ -52,9 +52,9 @@ export class FikaRaidCallbacks { return this.httpResponseUtil.noBody(await this.fikaRaidController.handleRaidStartHeadless(sessionID, info)); } - /** Handle /fika/raid/headless/getstatus */ - public handleRaidGetStatusHeadless(_url: string, _info: any, _sessionID: string): string { - return this.httpResponseUtil.noBody(this.fikaRaidController.handleRaidGetStatusHeadless()); + /** Handle /fika/raid/headless/available */ + public handleRaidGetAvailableHeadlesses(_url: string, _info: any, _sessionID: string): string { + return this.httpResponseUtil.noBody(this.fikaRaidController.handleRaidGetAvailableHeadlesses()); } /** Handle /fika/raid/registerPlayer */ diff --git a/src/controllers/FikaRaidController.ts b/src/controllers/FikaRaidController.ts index f101040f..a02b9522 100644 --- a/src/controllers/FikaRaidController.ts +++ b/src/controllers/FikaRaidController.ts @@ -9,12 +9,12 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { FikaHeadlessHelper } from "../helpers/FikaHeadlessHelper"; import { EFikaMatchEndSessionMessage } from "../models/enums/EFikaMatchEndSessionMessages"; import { EFikaNotifications } from "../models/enums/EFikaNotifications"; +import { IHeadlessAvailableClients } from "../models/fika/headless/IHeadlessAvailableClients"; import { IFikaRaidServerIdRequestData } from "../models/fika/routes/raid/IFikaRaidServerIdRequestData"; import { IFikaRaidCreateRequestData } from "../models/fika/routes/raid/create/IFikaRaidCreateRequestData"; import { IFikaRaidCreateResponse } from "../models/fika/routes/raid/create/IFikaRaidCreateResponse"; import { IFikaRaidGethostResponse } from "../models/fika/routes/raid/gethost/IFikaRaidGethostResponse"; import { IFikaRaidSettingsResponse } from "../models/fika/routes/raid/getsettings/IFikaRaidSettingsResponse"; -import { IGetStatusHeadlessResponse } from "../models/fika/routes/raid/headless/IGetStatusHeadlessResponse"; import { IStartHeadlessRequest } from "../models/fika/routes/raid/headless/IStartHeadlessRequest"; import { IStartHeadlessResponse } from "../models/fika/routes/raid/headless/IStartHeadlessResponse"; import { IFikaRaidJoinRequestData } from "../models/fika/routes/raid/join/IFikaRaidJoinRequestData"; @@ -133,10 +133,10 @@ export class FikaRaidController { /** Handle /fika/raid/headless/start */ public async handleRaidStartHeadless(sessionID: string, info: IStartHeadlessRequest): Promise { - if (!this.fikaHeadlessHelper.HeadlessClientsAvailable()) { + if (!this.fikaHeadlessHelper.isHeadlessClientAvailable(info.headlessSessionID)) { return { matchId: null, - error: "No headless clients are available.", + error: "This headless client is not available.", }; } @@ -147,7 +147,7 @@ export class FikaRaidController { }; } - const headlessClientId = await this.fikaHeadlessService.startHeadlessRaid(sessionID, info); + const headlessClientId = await this.fikaHeadlessService.startHeadlessRaid(info.headlessSessionID, sessionID, info); this.logger.info(`Sent WS fikaHeadlessStartRaid to ${headlessClientId}`); @@ -158,11 +158,9 @@ export class FikaRaidController { }; } - /** Handle /fika/raid/headless/getstatus */ - public handleRaidGetStatusHeadless(): IGetStatusHeadlessResponse { - return { - available: this.fikaHeadlessHelper.HeadlessClientsAvailable(), - }; + /** Handle /fika/raid/headless/available */ + public handleRaidGetAvailableHeadlesses(): IHeadlessAvailableClients[] { + return this.fikaHeadlessHelper.getAvailableHeadlessClients(); } /** Handle /fika/raid/registerPlayer */ diff --git a/src/helpers/FikaHeadlessHelper.ts b/src/helpers/FikaHeadlessHelper.ts index 420bf775..4b90f8c8 100644 --- a/src/helpers/FikaHeadlessHelper.ts +++ b/src/helpers/FikaHeadlessHelper.ts @@ -4,6 +4,7 @@ import type { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; import { EHeadlessStatus } from "../models/enums/EHeadlessStatus"; +import { IHeadlessAvailableClients } from "../models/fika/headless/IHeadlessAvailableClients"; import { FikaHeadlessProfileService } from "../services/headless/FikaHeadlessProfileService"; import { FikaHeadlessService } from "../services/headless/FikaHeadlessService"; import { FikaConfig } from "../utils/FikaConfig"; @@ -26,12 +27,22 @@ export class FikaHeadlessHelper { } /** - * Allows for checking if there are any headless clients available + * Allows for checking if the given headless client is available * - * @returns Returns true if one is available, returns false if none are available. + * @returns Returns true if it's available, returns false if it isn't available. */ - public HeadlessClientsAvailable(): boolean { - return Array.from(this.FikaHeadlessService.getHeadlessClients().values()).some((client) => client.state === EHeadlessStatus.READY); + public isHeadlessClientAvailable(headlessSessionID: string): boolean { + const headless = this.FikaHeadlessService.getHeadlessClients().get(headlessSessionID); + + if (!headless) { + return false; + } + + if (headless.state === EHeadlessStatus.READY) { + return true; + } + + return false; } /** @@ -39,8 +50,8 @@ export class FikaHeadlessHelper { * * @returns The nickname if the headless has been requested by a user, returns null if not. */ - public getRequesterUsername(headlessClientId: string): string | null { - const headlessClient = this.FikaHeadlessService.getHeadlessClients().get(headlessClientId); + public getRequesterUsername(headlessSessionID: string): string | null { + const headlessClient = this.FikaHeadlessService.getHeadlessClients().get(headlessSessionID); if (!headlessClient) { return null; @@ -58,13 +69,35 @@ export class FikaHeadlessHelper { * * @returns the alias, or nickname or the headless client. */ - public getHeadlessNickname(sessionId: string): string { - const AliasName = this.fikaConfig.getConfig().headless.profiles.aliases[sessionId]; + public getHeadlessNickname(headlessSessionID: string): string { + const AliasName = this.fikaConfig.getConfig().headless.profiles.aliases[headlessSessionID]; if (!AliasName) { - return this.saveServer.getProfile(sessionId).characters.pmc.Info.Nickname; + return this.saveServer.getProfile(headlessSessionID).characters.pmc.Info.Nickname; } return AliasName; } + + /** + * Gets all available headless clients + * + * @returns Returns an array of available headless clients + */ + public getAvailableHeadlessClients(): IHeadlessAvailableClients[] { + const headlessClients: IHeadlessAvailableClients[] = []; + + for (const [headlessSessionID, headless] of this.FikaHeadlessService.getHeadlessClients()) { + if (headless.state === EHeadlessStatus.READY) { + const availableHeadlessClient: IHeadlessAvailableClients = { + headlessSessionID: headlessSessionID, + alias: this.getHeadlessNickname(headlessSessionID), + }; + + headlessClients.push(availableHeadlessClient); + } + + return headlessClients; + } + } } diff --git a/src/models/fika/headless/IHeadlessAvailableClients.ts b/src/models/fika/headless/IHeadlessAvailableClients.ts new file mode 100644 index 00000000..c29138ba --- /dev/null +++ b/src/models/fika/headless/IHeadlessAvailableClients.ts @@ -0,0 +1,6 @@ +export interface IHeadlessAvailableClients { + /** SessionID of the headless client */ + headlessSessionID: string; + /** The alias of the headless client, if it has any assigned. If it doesn't have any assigned uses the nickname */ + alias: string; +} diff --git a/src/models/fika/routes/raid/headless/IGetStatusHeadlessResponse.ts b/src/models/fika/routes/raid/headless/IGetStatusHeadlessResponse.ts deleted file mode 100644 index 6f45b304..00000000 --- a/src/models/fika/routes/raid/headless/IGetStatusHeadlessResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface IGetStatusHeadlessResponse { - available: boolean; -} diff --git a/src/models/fika/routes/raid/headless/IStartHeadlessRequest.ts b/src/models/fika/routes/raid/headless/IStartHeadlessRequest.ts index 40927eb2..508b4541 100644 --- a/src/models/fika/routes/raid/headless/IStartHeadlessRequest.ts +++ b/src/models/fika/routes/raid/headless/IStartHeadlessRequest.ts @@ -4,6 +4,7 @@ import { PlayersSpawnPlace } from "@spt/models/enums/PlayersSpawnPlace"; import { SideType } from "@spt/models/enums/SideType"; export interface IStartHeadlessRequest { + headlessSessionID: string; time: DateTime; locationId: string; spawnPlace: PlayersSpawnPlace; diff --git a/src/routers/static/FikaRaidStaticRouter.ts b/src/routers/static/FikaRaidStaticRouter.ts index 7191c2cc..ed0bdd16 100644 --- a/src/routers/static/FikaRaidStaticRouter.ts +++ b/src/routers/static/FikaRaidStaticRouter.ts @@ -33,8 +33,8 @@ export class FikaRaidStaticRouter extends StaticRouter { new RouteAction("/fika/raid/headless/start", async (url: string, info: IStartHeadlessRequest, sessionID: string, _output: string): Promise => { return this.fikaRaidCallbacks.handleRaidStartHeadless(url, info, sessionID); }), - new RouteAction("/fika/raid/headless/getstatus", async (url: string, info: any, sessionID: string, _output: string): Promise => { - return this.fikaRaidCallbacks.handleRaidGetStatusHeadless(url, info, sessionID); + new RouteAction("/fika/raid/headless/available", async (url: string, info: any, sessionID: string, _output: string): Promise => { + return this.fikaRaidCallbacks.handleRaidGetAvailableHeadlesses(url, info, sessionID); }), new RouteAction("/fika/raid/registerPlayer", async (url: string, info: IRegisterPlayerRequestData, sessionID: string, _output: string): Promise => { return this.fikaRaidCallbacks.handleRaidRegisterPlayer(url, info, sessionID); diff --git a/src/services/headless/FikaHeadlessService.ts b/src/services/headless/FikaHeadlessService.ts index 8f00db8a..3d22ef66 100644 --- a/src/services/headless/FikaHeadlessService.ts +++ b/src/services/headless/FikaHeadlessService.ts @@ -38,16 +38,10 @@ export class FikaHeadlessService { /** Begin setting up a raid for a headless client * - * @returns returns a SessionID of the headless client that is starting this raid, returns null if no client could be found or there was an error. + * @returns returns the SessionID of the headless client that is starting this raid, returns null if no client could be found or there was an error. */ - public async startHeadlessRaid(requesterSessionID: string, info: IStartHeadlessRequest): Promise { - const headlessClientId = this.getAvailableHeadlessClient(); - - if (!headlessClientId) { - return null; - } - - const headlessClient = this.headlessClients.get(headlessClientId); + public async startHeadlessRaid(headlessSessionID: string, requesterSessionID: string, info: IStartHeadlessRequest): Promise { + const headlessClient = this.headlessClients.get(headlessSessionID); if (!headlessClient || headlessClient?.state != EHeadlessStatus.READY) { return null; @@ -75,7 +69,7 @@ export class FikaHeadlessService { await headlessClientWS.sendAsync(JSON.stringify(startRequest)); - return headlessClientId; + return headlessSessionID; } /** Sends a join message to the requester of a headless client */