diff --git a/src/controllers/api/getShipController.ts b/src/controllers/api/getShipController.ts index 10f6e25f..ac1ebadf 100644 --- a/src/controllers/api/getShipController.ts +++ b/src/controllers/api/getShipController.ts @@ -26,7 +26,10 @@ export const getShipController: RequestHandler = async (req, res) => { Colors: personalRooms.ShipInteriorColors, ShipAttachments: ship.ShipAttachments, SkinFlavourItem: ship.SkinFlavourItem - } + }, + FavouriteLoadoutId: personalRooms.Ship.FavouriteLoadoutId + ? toOid(personalRooms.Ship.FavouriteLoadoutId) + : undefined }, Apartment: personalRooms.Apartment, TailorShop: personalRooms.TailorShop diff --git a/src/controllers/api/setShipFavouriteLoadoutController.ts b/src/controllers/api/setShipFavouriteLoadoutController.ts index d798e0ed..e4bf2e13 100644 --- a/src/controllers/api/setShipFavouriteLoadoutController.ts +++ b/src/controllers/api/setShipFavouriteLoadoutController.ts @@ -3,29 +3,40 @@ import { RequestHandler } from "express"; import { getPersonalRooms } from "@/src/services/personalRoomsService"; import { IOid } from "@/src/types/commonTypes"; import { Types } from "mongoose"; +import { IFavouriteLoadoutDatabase, TBootLocation } from "@/src/types/shipTypes"; export const setShipFavouriteLoadoutController: RequestHandler = async (req, res) => { const accountId = await getAccountIdForRequest(req); const personalRooms = await getPersonalRooms(accountId); const body = JSON.parse(String(req.body)) as ISetShipFavouriteLoadoutRequest; - if (body.BootLocation != "SHOP") { - throw new Error(`unexpected BootLocation: ${body.BootLocation}`); - } - const display = personalRooms.TailorShop.FavouriteLoadouts.find(x => x.Tag == body.TagName); - if (display) { - display.LoadoutId = new Types.ObjectId(body.FavouriteLoadoutId.$oid); + if (body.BootLocation == "LISET") { + personalRooms.Ship.FavouriteLoadoutId = new Types.ObjectId(body.FavouriteLoadoutId.$oid); + } else if (body.BootLocation == "APARTMENT") { + updateTaggedDisplay(personalRooms.Apartment.FavouriteLoadouts, body); + } else if (body.BootLocation == "SHOP") { + updateTaggedDisplay(personalRooms.TailorShop.FavouriteLoadouts, body); } else { - personalRooms.TailorShop.FavouriteLoadouts.push({ - Tag: body.TagName, - LoadoutId: new Types.ObjectId(body.FavouriteLoadoutId.$oid) - }); + console.log(body); + throw new Error(`unexpected BootLocation: ${body.BootLocation}`); } await personalRooms.save(); res.json({}); }; interface ISetShipFavouriteLoadoutRequest { - BootLocation: string; + BootLocation: TBootLocation; FavouriteLoadoutId: IOid; - TagName: string; + TagName?: string; } + +const updateTaggedDisplay = (arr: IFavouriteLoadoutDatabase[], body: ISetShipFavouriteLoadoutRequest): void => { + const display = arr.find(x => x.Tag == body.TagName!); + if (display) { + display.LoadoutId = new Types.ObjectId(body.FavouriteLoadoutId.$oid); + } else { + arr.push({ + Tag: body.TagName!, + LoadoutId: new Types.ObjectId(body.FavouriteLoadoutId.$oid) + }); + } +}; diff --git a/src/controllers/api/setShipVignetteController.ts b/src/controllers/api/setShipVignetteController.ts new file mode 100644 index 00000000..a1d991da --- /dev/null +++ b/src/controllers/api/setShipVignetteController.ts @@ -0,0 +1,48 @@ +import { addMiscItems, combineInventoryChanges, getInventory } from "@/src/services/inventoryService"; +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getPersonalRooms } from "@/src/services/personalRoomsService"; +import { IInventoryChanges } from "@/src/types/purchaseTypes"; +import { logger } from "@/src/utils/logger"; +import { RequestHandler } from "express"; + +export const setShipVignetteController: RequestHandler = async (req, res) => { + const accountId = await getAccountIdForRequest(req); + const inventory = await getInventory(accountId, "MiscItems"); + const personalRooms = await getPersonalRooms(accountId); + const body = JSON.parse(String(req.body)) as ISetShipVignetteRequest; + personalRooms.Ship.Wallpaper = body.Wallpaper; + personalRooms.Ship.Vignette = body.Vignette; + personalRooms.Ship.VignetteFish ??= []; + const inventoryChanges: IInventoryChanges = {}; + for (let i = 0; i != body.Fish.length; ++i) { + if (body.Fish[i] && !personalRooms.Ship.VignetteFish[i]) { + logger.debug(`moving ${body.Fish[i]} from inventory to vignette slot ${i}`); + const miscItemsDelta = [{ ItemType: body.Fish[i], ItemCount: -1 }]; + addMiscItems(inventory, miscItemsDelta); + combineInventoryChanges(inventoryChanges, { MiscItems: miscItemsDelta }); + } else if (personalRooms.Ship.VignetteFish[i] && !body.Fish[i]) { + logger.debug(`moving ${personalRooms.Ship.VignetteFish[i]} from vignette slot ${i} to inventory`); + const miscItemsDelta = [{ ItemType: personalRooms.Ship.VignetteFish[i], ItemCount: +1 }]; + addMiscItems(inventory, miscItemsDelta); + combineInventoryChanges(inventoryChanges, { MiscItems: miscItemsDelta }); + } + } + personalRooms.Ship.VignetteFish = body.Fish; + if (body.VignetteDecos.length) { + logger.error(`setShipVignette request not fully handled:`, body); + } + await Promise.all([inventory.save(), personalRooms.save()]); + res.json({ + Wallpaper: body.Wallpaper, + Vignette: body.Vignette, + VignetteFish: body.Fish, + InventoryChanges: inventoryChanges + }); +}; + +interface ISetShipVignetteRequest { + Wallpaper: string; + Vignette: string; + Fish: string[]; + VignetteDecos: unknown[]; +} diff --git a/src/models/personalRoomsModel.ts b/src/models/personalRoomsModel.ts index 1c6a7c6d..0fcdda72 100644 --- a/src/models/personalRoomsModel.ts +++ b/src/models/personalRoomsModel.ts @@ -2,13 +2,13 @@ import { toOid } from "@/src/helpers/inventoryHelpers"; import { colorSchema } from "@/src/models/inventoryModels/inventoryModel"; import { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes"; import { - IApartment, IFavouriteLoadoutDatabase, IGardening, IPlacedDecosDatabase, IPictureFrameInfo, IRoom, - ITailorShopDatabase + ITailorShopDatabase, + IApartmentDatabase } from "@/src/types/shipTypes"; import { Schema, model } from "mongoose"; @@ -62,19 +62,34 @@ const roomSchema = new Schema( { _id: false } ); +const favouriteLoadoutSchema = new Schema( + { + Tag: String, + LoadoutId: Schema.Types.ObjectId + }, + { _id: false } +); +favouriteLoadoutSchema.set("toJSON", { + virtuals: true, + transform(_document, returnedObject) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + returnedObject.LoadoutId = toOid(returnedObject.LoadoutId); + } +}); + const gardeningSchema = new Schema({ Planters: [Schema.Types.Mixed] //TODO: add when implementing gardening }); -const apartmentSchema = new Schema( +const apartmentSchema = new Schema( { Rooms: [roomSchema], - FavouriteLoadouts: [Schema.Types.Mixed], + FavouriteLoadouts: [favouriteLoadoutSchema], Gardening: gardeningSchema // TODO: ensure this is correct }, { _id: false } ); -const apartmentDefault: IApartment = { +const apartmentDefault: IApartmentDatabase = { Rooms: [ { Name: "ElevatorLanding", MaxCapacity: 1600 }, { Name: "ApartmentRoomA", MaxCapacity: 1000 }, @@ -90,6 +105,10 @@ const orbiterSchema = new Schema( { Features: [String], Rooms: [roomSchema], + VignetteFish: { type: [String], default: undefined }, + FavouriteLoadoutId: Schema.Types.ObjectId, + Wallpaper: String, + Vignette: String, ContentUrlSignature: { type: String, required: false }, BootLocation: String }, @@ -107,21 +126,6 @@ const orbiterDefault: IOrbiter = { ] }; -const favouriteLoadoutSchema = new Schema( - { - Tag: String, - LoadoutId: Schema.Types.ObjectId - }, - { _id: false } -); -favouriteLoadoutSchema.set("toJSON", { - virtuals: true, - transform(_document, returnedObject) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - returnedObject.LoadoutId = toOid(returnedObject.LoadoutId); - } -}); - const tailorShopSchema = new Schema( { FavouriteLoadouts: [favouriteLoadoutSchema], diff --git a/src/routes/api.ts b/src/routes/api.ts index 41a6cf0b..bd3ffd4b 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -115,6 +115,7 @@ import { setGuildMotdController } from "@/src/controllers/api/setGuildMotdContro import { setPlacedDecoInfoController } from "@/src/controllers/api/setPlacedDecoInfoController"; import { setShipCustomizationsController } from "@/src/controllers/api/setShipCustomizationsController"; import { setShipFavouriteLoadoutController } from "@/src/controllers/api/setShipFavouriteLoadoutController"; +import { setShipVignetteController } from "@/src/controllers/api/setShipVignetteController"; import { setSupportedSyndicateController } from "@/src/controllers/api/setSupportedSyndicateController"; import { setWeaponSkillTreeController } from "@/src/controllers/api/setWeaponSkillTreeController"; import { shipDecorationsController } from "@/src/controllers/api/shipDecorationsController"; @@ -277,6 +278,7 @@ apiRouter.post("/setGuildMotd.php", setGuildMotdController); apiRouter.post("/setPlacedDecoInfo.php", setPlacedDecoInfoController); apiRouter.post("/setShipCustomizations.php", setShipCustomizationsController); apiRouter.post("/setShipFavouriteLoadout.php", setShipFavouriteLoadoutController); +apiRouter.post("/setShipVignette.php", setShipVignetteController); apiRouter.post("/setWeaponSkillTree.php", setWeaponSkillTreeController); apiRouter.post("/shipDecorations.php", shipDecorationsController); apiRouter.post("/startCollectibleEntry.php", startCollectibleEntryController); diff --git a/src/types/personalRoomsTypes.ts b/src/types/personalRoomsTypes.ts index fb672955..68239bb4 100644 --- a/src/types/personalRoomsTypes.ts +++ b/src/types/personalRoomsTypes.ts @@ -5,13 +5,18 @@ import { IPlacedDecosDatabase, ITailorShop, ITailorShopDatabase, - TBootLocation + TBootLocation, + IApartmentDatabase } from "@/src/types/shipTypes"; import { Document, Model, Types } from "mongoose"; export interface IOrbiter { Features: string[]; Rooms: IRoom[]; + VignetteFish?: string[]; + FavouriteLoadoutId?: Types.ObjectId; + Wallpaper?: string; + Vignette?: string; ContentUrlSignature?: string; BootLocation?: TBootLocation; } @@ -28,7 +33,7 @@ export interface IPersonalRoomsDatabase { personalRoomsOwnerId: Types.ObjectId; activeShipId: Types.ObjectId; Ship: IOrbiter; - Apartment: IApartment; + Apartment: IApartmentDatabase; TailorShop: ITailorShopDatabase; } @@ -38,7 +43,7 @@ export type PersonalRoomsDocumentProps = { Ship: Omit & { Rooms: RoomsType[]; }; - Apartment: Omit & { + Apartment: Omit & { Rooms: RoomsType[]; }; TailorShop: Omit & { diff --git a/src/types/shipTypes.ts b/src/types/shipTypes.ts index 23c46c48..a097f3ca 100644 --- a/src/types/shipTypes.ts +++ b/src/types/shipTypes.ts @@ -28,8 +28,12 @@ export interface IShip { ShipId: IOid; ShipInterior: IShipInterior; Rooms: IRoom[]; - ContentUrlSignature?: string; + VignetteFish?: string[]; + FavouriteLoadoutId?: IOid; + Wallpaper?: string; + Vignette?: string; BootLocation?: TBootLocation; + ContentUrlSignature?: string; } export interface IShipDatabase { @@ -60,10 +64,17 @@ export interface IPlanters { export interface IGardening { Planters?: IPlanters[]; } + export interface IApartment { Gardening: IGardening; Rooms: IRoom[]; - FavouriteLoadouts: string[]; + FavouriteLoadouts: IFavouriteLoadout[]; +} + +export interface IApartmentDatabase { + Gardening: IGardening; + Rooms: IRoom[]; + FavouriteLoadouts: IFavouriteLoadoutDatabase[]; } export interface IPlacedDecosDatabase {