forked from OpenWF/SpaceNinjaServer
feat: personal quarters loadout, stencil, vignette, & fish customisation (#1619)
Closes #1618 Reviewed-on: OpenWF/SpaceNinjaServer#1619 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
c64d466ce1
commit
827ea47468
@ -26,7 +26,10 @@ export const getShipController: RequestHandler = async (req, res) => {
|
|||||||
Colors: personalRooms.ShipInteriorColors,
|
Colors: personalRooms.ShipInteriorColors,
|
||||||
ShipAttachments: ship.ShipAttachments,
|
ShipAttachments: ship.ShipAttachments,
|
||||||
SkinFlavourItem: ship.SkinFlavourItem
|
SkinFlavourItem: ship.SkinFlavourItem
|
||||||
}
|
},
|
||||||
|
FavouriteLoadoutId: personalRooms.Ship.FavouriteLoadoutId
|
||||||
|
? toOid(personalRooms.Ship.FavouriteLoadoutId)
|
||||||
|
: undefined
|
||||||
},
|
},
|
||||||
Apartment: personalRooms.Apartment,
|
Apartment: personalRooms.Apartment,
|
||||||
TailorShop: personalRooms.TailorShop
|
TailorShop: personalRooms.TailorShop
|
||||||
|
@ -3,29 +3,40 @@ import { RequestHandler } from "express";
|
|||||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||||
import { IOid } from "@/src/types/commonTypes";
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
|
import { IFavouriteLoadoutDatabase, TBootLocation } from "@/src/types/shipTypes";
|
||||||
|
|
||||||
export const setShipFavouriteLoadoutController: RequestHandler = async (req, res) => {
|
export const setShipFavouriteLoadoutController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const personalRooms = await getPersonalRooms(accountId);
|
const personalRooms = await getPersonalRooms(accountId);
|
||||||
const body = JSON.parse(String(req.body)) as ISetShipFavouriteLoadoutRequest;
|
const body = JSON.parse(String(req.body)) as ISetShipFavouriteLoadoutRequest;
|
||||||
if (body.BootLocation != "SHOP") {
|
if (body.BootLocation == "LISET") {
|
||||||
throw new Error(`unexpected BootLocation: ${body.BootLocation}`);
|
personalRooms.Ship.FavouriteLoadoutId = new Types.ObjectId(body.FavouriteLoadoutId.$oid);
|
||||||
}
|
} else if (body.BootLocation == "APARTMENT") {
|
||||||
const display = personalRooms.TailorShop.FavouriteLoadouts.find(x => x.Tag == body.TagName);
|
updateTaggedDisplay(personalRooms.Apartment.FavouriteLoadouts, body);
|
||||||
if (display) {
|
} else if (body.BootLocation == "SHOP") {
|
||||||
display.LoadoutId = new Types.ObjectId(body.FavouriteLoadoutId.$oid);
|
updateTaggedDisplay(personalRooms.TailorShop.FavouriteLoadouts, body);
|
||||||
} else {
|
} else {
|
||||||
personalRooms.TailorShop.FavouriteLoadouts.push({
|
console.log(body);
|
||||||
Tag: body.TagName,
|
throw new Error(`unexpected BootLocation: ${body.BootLocation}`);
|
||||||
LoadoutId: new Types.ObjectId(body.FavouriteLoadoutId.$oid)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
await personalRooms.save();
|
await personalRooms.save();
|
||||||
res.json({});
|
res.json({});
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ISetShipFavouriteLoadoutRequest {
|
interface ISetShipFavouriteLoadoutRequest {
|
||||||
BootLocation: string;
|
BootLocation: TBootLocation;
|
||||||
FavouriteLoadoutId: IOid;
|
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)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
48
src/controllers/api/setShipVignetteController.ts
Normal file
48
src/controllers/api/setShipVignetteController.ts
Normal file
@ -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[];
|
||||||
|
}
|
@ -2,13 +2,13 @@ import { toOid } from "@/src/helpers/inventoryHelpers";
|
|||||||
import { colorSchema } from "@/src/models/inventoryModels/inventoryModel";
|
import { colorSchema } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
import { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
|
import { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
|
||||||
import {
|
import {
|
||||||
IApartment,
|
|
||||||
IFavouriteLoadoutDatabase,
|
IFavouriteLoadoutDatabase,
|
||||||
IGardening,
|
IGardening,
|
||||||
IPlacedDecosDatabase,
|
IPlacedDecosDatabase,
|
||||||
IPictureFrameInfo,
|
IPictureFrameInfo,
|
||||||
IRoom,
|
IRoom,
|
||||||
ITailorShopDatabase
|
ITailorShopDatabase,
|
||||||
|
IApartmentDatabase
|
||||||
} from "@/src/types/shipTypes";
|
} from "@/src/types/shipTypes";
|
||||||
import { Schema, model } from "mongoose";
|
import { Schema, model } from "mongoose";
|
||||||
|
|
||||||
@ -62,19 +62,34 @@ const roomSchema = new Schema<IRoom>(
|
|||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const favouriteLoadoutSchema = new Schema<IFavouriteLoadoutDatabase>(
|
||||||
|
{
|
||||||
|
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<IGardening>({
|
const gardeningSchema = new Schema<IGardening>({
|
||||||
Planters: [Schema.Types.Mixed] //TODO: add when implementing gardening
|
Planters: [Schema.Types.Mixed] //TODO: add when implementing gardening
|
||||||
});
|
});
|
||||||
|
|
||||||
const apartmentSchema = new Schema<IApartment>(
|
const apartmentSchema = new Schema<IApartmentDatabase>(
|
||||||
{
|
{
|
||||||
Rooms: [roomSchema],
|
Rooms: [roomSchema],
|
||||||
FavouriteLoadouts: [Schema.Types.Mixed],
|
FavouriteLoadouts: [favouriteLoadoutSchema],
|
||||||
Gardening: gardeningSchema // TODO: ensure this is correct
|
Gardening: gardeningSchema // TODO: ensure this is correct
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
const apartmentDefault: IApartment = {
|
const apartmentDefault: IApartmentDatabase = {
|
||||||
Rooms: [
|
Rooms: [
|
||||||
{ Name: "ElevatorLanding", MaxCapacity: 1600 },
|
{ Name: "ElevatorLanding", MaxCapacity: 1600 },
|
||||||
{ Name: "ApartmentRoomA", MaxCapacity: 1000 },
|
{ Name: "ApartmentRoomA", MaxCapacity: 1000 },
|
||||||
@ -90,6 +105,10 @@ const orbiterSchema = new Schema<IOrbiter>(
|
|||||||
{
|
{
|
||||||
Features: [String],
|
Features: [String],
|
||||||
Rooms: [roomSchema],
|
Rooms: [roomSchema],
|
||||||
|
VignetteFish: { type: [String], default: undefined },
|
||||||
|
FavouriteLoadoutId: Schema.Types.ObjectId,
|
||||||
|
Wallpaper: String,
|
||||||
|
Vignette: String,
|
||||||
ContentUrlSignature: { type: String, required: false },
|
ContentUrlSignature: { type: String, required: false },
|
||||||
BootLocation: String
|
BootLocation: String
|
||||||
},
|
},
|
||||||
@ -107,21 +126,6 @@ const orbiterDefault: IOrbiter = {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const favouriteLoadoutSchema = new Schema<IFavouriteLoadoutDatabase>(
|
|
||||||
{
|
|
||||||
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<ITailorShopDatabase>(
|
const tailorShopSchema = new Schema<ITailorShopDatabase>(
|
||||||
{
|
{
|
||||||
FavouriteLoadouts: [favouriteLoadoutSchema],
|
FavouriteLoadouts: [favouriteLoadoutSchema],
|
||||||
|
@ -115,6 +115,7 @@ import { setGuildMotdController } from "@/src/controllers/api/setGuildMotdContro
|
|||||||
import { setPlacedDecoInfoController } from "@/src/controllers/api/setPlacedDecoInfoController";
|
import { setPlacedDecoInfoController } from "@/src/controllers/api/setPlacedDecoInfoController";
|
||||||
import { setShipCustomizationsController } from "@/src/controllers/api/setShipCustomizationsController";
|
import { setShipCustomizationsController } from "@/src/controllers/api/setShipCustomizationsController";
|
||||||
import { setShipFavouriteLoadoutController } from "@/src/controllers/api/setShipFavouriteLoadoutController";
|
import { setShipFavouriteLoadoutController } from "@/src/controllers/api/setShipFavouriteLoadoutController";
|
||||||
|
import { setShipVignetteController } from "@/src/controllers/api/setShipVignetteController";
|
||||||
import { setSupportedSyndicateController } from "@/src/controllers/api/setSupportedSyndicateController";
|
import { setSupportedSyndicateController } from "@/src/controllers/api/setSupportedSyndicateController";
|
||||||
import { setWeaponSkillTreeController } from "@/src/controllers/api/setWeaponSkillTreeController";
|
import { setWeaponSkillTreeController } from "@/src/controllers/api/setWeaponSkillTreeController";
|
||||||
import { shipDecorationsController } from "@/src/controllers/api/shipDecorationsController";
|
import { shipDecorationsController } from "@/src/controllers/api/shipDecorationsController";
|
||||||
@ -277,6 +278,7 @@ apiRouter.post("/setGuildMotd.php", setGuildMotdController);
|
|||||||
apiRouter.post("/setPlacedDecoInfo.php", setPlacedDecoInfoController);
|
apiRouter.post("/setPlacedDecoInfo.php", setPlacedDecoInfoController);
|
||||||
apiRouter.post("/setShipCustomizations.php", setShipCustomizationsController);
|
apiRouter.post("/setShipCustomizations.php", setShipCustomizationsController);
|
||||||
apiRouter.post("/setShipFavouriteLoadout.php", setShipFavouriteLoadoutController);
|
apiRouter.post("/setShipFavouriteLoadout.php", setShipFavouriteLoadoutController);
|
||||||
|
apiRouter.post("/setShipVignette.php", setShipVignetteController);
|
||||||
apiRouter.post("/setWeaponSkillTree.php", setWeaponSkillTreeController);
|
apiRouter.post("/setWeaponSkillTree.php", setWeaponSkillTreeController);
|
||||||
apiRouter.post("/shipDecorations.php", shipDecorationsController);
|
apiRouter.post("/shipDecorations.php", shipDecorationsController);
|
||||||
apiRouter.post("/startCollectibleEntry.php", startCollectibleEntryController);
|
apiRouter.post("/startCollectibleEntry.php", startCollectibleEntryController);
|
||||||
|
@ -5,13 +5,18 @@ import {
|
|||||||
IPlacedDecosDatabase,
|
IPlacedDecosDatabase,
|
||||||
ITailorShop,
|
ITailorShop,
|
||||||
ITailorShopDatabase,
|
ITailorShopDatabase,
|
||||||
TBootLocation
|
TBootLocation,
|
||||||
|
IApartmentDatabase
|
||||||
} from "@/src/types/shipTypes";
|
} from "@/src/types/shipTypes";
|
||||||
import { Document, Model, Types } from "mongoose";
|
import { Document, Model, Types } from "mongoose";
|
||||||
|
|
||||||
export interface IOrbiter {
|
export interface IOrbiter {
|
||||||
Features: string[];
|
Features: string[];
|
||||||
Rooms: IRoom[];
|
Rooms: IRoom[];
|
||||||
|
VignetteFish?: string[];
|
||||||
|
FavouriteLoadoutId?: Types.ObjectId;
|
||||||
|
Wallpaper?: string;
|
||||||
|
Vignette?: string;
|
||||||
ContentUrlSignature?: string;
|
ContentUrlSignature?: string;
|
||||||
BootLocation?: TBootLocation;
|
BootLocation?: TBootLocation;
|
||||||
}
|
}
|
||||||
@ -28,7 +33,7 @@ export interface IPersonalRoomsDatabase {
|
|||||||
personalRoomsOwnerId: Types.ObjectId;
|
personalRoomsOwnerId: Types.ObjectId;
|
||||||
activeShipId: Types.ObjectId;
|
activeShipId: Types.ObjectId;
|
||||||
Ship: IOrbiter;
|
Ship: IOrbiter;
|
||||||
Apartment: IApartment;
|
Apartment: IApartmentDatabase;
|
||||||
TailorShop: ITailorShopDatabase;
|
TailorShop: ITailorShopDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +43,7 @@ export type PersonalRoomsDocumentProps = {
|
|||||||
Ship: Omit<IOrbiter, "Rooms"> & {
|
Ship: Omit<IOrbiter, "Rooms"> & {
|
||||||
Rooms: RoomsType[];
|
Rooms: RoomsType[];
|
||||||
};
|
};
|
||||||
Apartment: Omit<IApartment, "Rooms"> & {
|
Apartment: Omit<IApartmentDatabase, "Rooms"> & {
|
||||||
Rooms: RoomsType[];
|
Rooms: RoomsType[];
|
||||||
};
|
};
|
||||||
TailorShop: Omit<ITailorShopDatabase, "Rooms"> & {
|
TailorShop: Omit<ITailorShopDatabase, "Rooms"> & {
|
||||||
|
@ -28,8 +28,12 @@ export interface IShip {
|
|||||||
ShipId: IOid;
|
ShipId: IOid;
|
||||||
ShipInterior: IShipInterior;
|
ShipInterior: IShipInterior;
|
||||||
Rooms: IRoom[];
|
Rooms: IRoom[];
|
||||||
ContentUrlSignature?: string;
|
VignetteFish?: string[];
|
||||||
|
FavouriteLoadoutId?: IOid;
|
||||||
|
Wallpaper?: string;
|
||||||
|
Vignette?: string;
|
||||||
BootLocation?: TBootLocation;
|
BootLocation?: TBootLocation;
|
||||||
|
ContentUrlSignature?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IShipDatabase {
|
export interface IShipDatabase {
|
||||||
@ -60,10 +64,17 @@ export interface IPlanters {
|
|||||||
export interface IGardening {
|
export interface IGardening {
|
||||||
Planters?: IPlanters[];
|
Planters?: IPlanters[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IApartment {
|
export interface IApartment {
|
||||||
Gardening: IGardening;
|
Gardening: IGardening;
|
||||||
Rooms: IRoom[];
|
Rooms: IRoom[];
|
||||||
FavouriteLoadouts: string[];
|
FavouriteLoadouts: IFavouriteLoadout[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApartmentDatabase {
|
||||||
|
Gardening: IGardening;
|
||||||
|
Rooms: IRoom[];
|
||||||
|
FavouriteLoadouts: IFavouriteLoadoutDatabase[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPlacedDecosDatabase {
|
export interface IPlacedDecosDatabase {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user