feat: articula customizations #2636

Merged
Sainan merged 2 commits from articula into main 2025-08-16 05:40:17 -07:00
6 changed files with 101 additions and 25 deletions

View File

@ -1,23 +1,19 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { RequestHandler } from "express";
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";
export const setPlacedDecoInfoController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest;
//console.log(JSON.stringify(payload, null, 2));
await handleSetPlacedDecoInfo(accountId, payload);
res.json({
DecoId: payload.DecoId,
IsPicture: true,
PictureFrameInfo: payload.PictureFrameInfo,
BootLocation: payload.BootLocation
...payload,
IsPicture: !!payload.PictureFrameInfo
} satisfies ISetPlacedDecoInfoResponse);
};
interface ISetPlacedDecoInfoResponse {
DecoId: string;
interface ISetPlacedDecoInfoResponse extends ISetPlacedDecoInfoRequest {
IsPicture: boolean;
PictureFrameInfo?: IPictureFrameInfo;
BootLocation?: string;
}

View File

@ -25,7 +25,7 @@ export const EquipmentSelectionSchema = new Schema<IEquipmentSelection>(
}
);
const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
export const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
{
FocusSchool: String,
PresetIcon: String,

View File

@ -1,6 +1,7 @@
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import {
IApartmentDatabase,
ICustomizationInfoDatabase,
IFavouriteLoadoutDatabase,
IGardeningDatabase,
IOrbiterClient,
@ -11,12 +12,13 @@ import {
IPlantClient,
IPlantDatabase,
IPlanterDatabase,
IRoom,
IRoomDatabase,
ITailorShopDatabase,
PersonalRoomsModelType
} from "@/src/types/personalRoomsTypes";
import { Schema, Types, model } from "mongoose";
import { colorSchema, shipCustomizationSchema } from "@/src/models/commonModel";
import { loadoutConfigSchema } from "@/src/models/inventoryModels/loadoutModel";
export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
{
@ -34,7 +36,20 @@ export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
TextColorB: Number,
TextOrientation: Number
},
{ id: false, _id: false }
{ _id: false }
);
export const customizationInfoSchema = new Schema<ICustomizationInfoDatabase>(
{
Anim: String,
AnimPose: Number,
LoadOutPreset: loadoutConfigSchema,
VehiclePreset: loadoutConfigSchema,
EquippedWeapon: String,
AvatarType: String,
LoadOutType: String
},
{ _id: false }
);
const placedDecosSchema = new Schema<IPlacedDecosDatabase>(
@ -44,7 +59,9 @@ const placedDecosSchema = new Schema<IPlacedDecosDatabase>(
Rot: [Number],
Scale: Number,
Sockets: Number,
PictureFrameInfo: { type: pictureFrameInfoSchema, default: undefined }
PictureFrameInfo: { type: pictureFrameInfoSchema, default: undefined },
CustomizationInfo: { type: customizationInfoSchema, default: undefined },
AnimPoseItem: String
},
{ id: false }
);
@ -60,7 +77,7 @@ placedDecosSchema.set("toJSON", {
}
});
const roomSchema = new Schema<IRoom>(
const roomSchema = new Schema<IRoomDatabase>(
{
Name: String,
MaxCapacity: Number,

View File

@ -47,16 +47,22 @@ import {
import {
IApartmentClient,
IApartmentDatabase,
ICustomizationInfoClient,
ICustomizationInfoDatabase,
IFavouriteLoadout,
IFavouriteLoadoutDatabase,
IGetShipResponse,
IOrbiterClient,
IOrbiterDatabase,
IPersonalRoomsDatabase,
IPlacedDecosClient,
IPlacedDecosDatabase,
IPlantClient,
IPlantDatabase,
IPlanterClient,
IPlanterDatabase,
IRoomClient,
IRoomDatabase,
ITailorShop,
ITailorShopDatabase
} from "@/src/types/personalRoomsTypes";
@ -446,6 +452,30 @@ export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPrese
db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig);
};
export const convertCustomizationInfo = (client: ICustomizationInfoClient): ICustomizationInfoDatabase => {
return {
...client,
LoadOutPreset: client.LoadOutPreset ? convertLoadOutConfig(client.LoadOutPreset) : undefined,
VehiclePreset: client.VehiclePreset ? convertLoadOutConfig(client.VehiclePreset) : undefined
};
};
const convertDeco = (client: IPlacedDecosClient): IPlacedDecosDatabase => {
const { id, ...rest } = client;
return {
...rest,
CustomizationInfo: client.CustomizationInfo ? convertCustomizationInfo(client.CustomizationInfo) : undefined,
_id: new Types.ObjectId(id.$oid)
};
};
const convertRoom = (client: IRoomClient): IRoomDatabase => {
return {
...client,
PlacedDecos: client.PlacedDecos ? client.PlacedDecos.map(convertDeco) : []
};
};
const convertShip = (client: IOrbiterClient): IOrbiterDatabase => {
return {
...client,
@ -453,6 +483,7 @@ const convertShip = (client: IOrbiterClient): IOrbiterDatabase => {
...client.ShipInterior,
Colors: Array.isArray(client.ShipInterior.Colors) ? {} : client.ShipInterior.Colors
},
Rooms: client.Rooms.map(convertRoom),
FavouriteLoadoutId: client.FavouriteLoadoutId ? new Types.ObjectId(client.FavouriteLoadoutId.$oid) : undefined
};
};
@ -481,6 +512,7 @@ const convertFavouriteLoadout = (client: IFavouriteLoadout): IFavouriteLoadoutDa
const convertApartment = (client: IApartmentClient): IApartmentDatabase => {
return {
...client,
Rooms: client.Rooms.map(convertRoom),
Gardening: { Planters: client.Gardening.Planters.map(convertPlanter) },
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};
@ -489,6 +521,7 @@ const convertApartment = (client: IApartmentClient): IApartmentDatabase => {
const convertTailorShop = (client: ITailorShop): ITailorShopDatabase => {
return {
...client,
Rooms: client.Rooms.map(convertRoom),
Colors: Array.isArray(client.Colors) ? {} : client.Colors,
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};

View File

@ -19,6 +19,7 @@ import { Guild } from "@/src/models/guildModel";
import { hasGuildPermission } from "@/src/services/guildService";
import { GuildPermission } from "@/src/types/guildTypes";
import { ExportResources } from "warframe-public-export-plus";
import { convertCustomizationInfo } from "@/src/services/importService";
export const setShipCustomizations = async (
accountId: string,
@ -269,6 +270,8 @@ export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlaced
}
placedDeco.PictureFrameInfo = req.PictureFrameInfo;
placedDeco.CustomizationInfo = req.CustomizationInfo ? convertCustomizationInfo(req.CustomizationInfo) : undefined;
placedDeco.AnimPoseItem = req.AnimPoseItem;
await personalRooms.save();
};

View File

@ -1,6 +1,6 @@
import { IColor, IShipAttachments, IShipCustomization } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { Document, Model, Types } from "mongoose";
import { ILoadoutClient } from "@/src/types/saveLoadoutTypes";
import { ILoadoutClient, ILoadoutConfigClient, ILoadoutConfigDatabase } from "@/src/types/saveLoadoutTypes";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
export interface IGetShipResponse {
@ -17,7 +17,7 @@ export interface IOrbiterClient {
Features: string[];
ShipId: IOid;
ShipInterior: IShipCustomization;
Rooms: IRoom[];
Rooms: IRoomClient[];
VignetteFish?: string[];
FavouriteLoadoutId?: IOid;
Wallpaper?: string;
@ -28,7 +28,7 @@ export interface IOrbiterClient {
export interface IOrbiterDatabase {
Features: string[];
Rooms: IRoom[];
Rooms: IRoomDatabase[];
ShipInterior?: IShipCustomization;
VignetteFish?: string[];
FavouriteLoadoutId?: Types.ObjectId;
@ -53,12 +53,18 @@ export interface IPersonalRoomsDatabase {
TailorShop: ITailorShopDatabase;
}
export interface IRoom {
export interface IRoomDatabase {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosDatabase[];
}
export interface IRoomClient {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosClient[];
}
export interface IPlantClient {
PlantType: string;
EndTime: IMongoDate;
@ -89,7 +95,7 @@ export interface IGardeningDatabase {
export interface IApartmentClient {
Gardening: IGardeningClient;
Rooms: IRoom[];
Rooms: IRoomClient[];
FavouriteLoadouts?: IFavouriteLoadout[];
VideoWallBackdrop?: string;
Soundscape?: string;
@ -97,7 +103,7 @@ export interface IApartmentClient {
export interface IApartmentDatabase {
Gardening: IGardeningDatabase;
Rooms: IRoom[];
Rooms: IRoomDatabase[];
FavouriteLoadouts: IFavouriteLoadoutDatabase[];
VideoWallBackdrop?: string;
Soundscape?: string;
@ -110,11 +116,14 @@ export interface IPlacedDecosDatabase {
Scale?: number;
Sockets?: number;
PictureFrameInfo?: IPictureFrameInfo;
CustomizationInfo?: ICustomizationInfoDatabase;
AnimPoseItem?: string;
_id: Types.ObjectId;
}
export interface IPlacedDecosClient extends Omit<IPlacedDecosDatabase, "_id"> {
export interface IPlacedDecosClient extends Omit<IPlacedDecosDatabase, "_id" | "CustomizationInfo"> {
id: IOid;
CustomizationInfo?: ICustomizationInfoClient;
}
export interface ISetShipCustomizationsRequest {
@ -166,11 +175,13 @@ export interface IResetShipDecorationsResponse {
}
export interface ISetPlacedDecoInfoRequest {
DecoType: string;
DecoType?: string;
DecoId: string;
Room: string;
PictureFrameInfo: IPictureFrameInfo;
PictureFrameInfo: IPictureFrameInfo; // IsPicture
CustomizationInfo?: ICustomizationInfoClient; // !IsPicture
BootLocation?: TBootLocation;
AnimPoseItem?: string; // !IsPicture
ComponentId?: string;
GuildId?: string;
}
@ -191,6 +202,21 @@ export interface IPictureFrameInfo {
TextOrientation: number;
}
export interface ICustomizationInfoClient {
Anim?: string;
AnimPose?: number;
LoadOutPreset?: ILoadoutConfigClient;
VehiclePreset?: ILoadoutConfigClient;
EquippedWeapon?: "SUIT_SLOT" | "LONG_GUN_SLOT" | "PISTOL_SLOT";
AvatarType?: string;
LoadOutType?: string; // "LOT_NORMAL"
}
export interface ICustomizationInfoDatabase extends Omit<ICustomizationInfoClient, "LoadOutPreset" | "VehiclePreset"> {
LoadOutPreset?: ILoadoutConfigDatabase;
VehiclePreset?: ILoadoutConfigDatabase;
}
export interface IFavouriteLoadout {
Tag: string;
LoadoutId: IOid;
@ -206,10 +232,11 @@ export interface ITailorShopDatabase {
Colors?: IColor;
CustomJson?: string;
LevelDecosVisible?: boolean;
Rooms: IRoom[];
Rooms: IRoomDatabase[];
}
export interface ITailorShop extends Omit<ITailorShopDatabase, "FavouriteLoadouts"> {
export interface ITailorShop extends Omit<ITailorShopDatabase, "Rooms" | "FavouriteLoadouts"> {
Rooms: IRoomClient[];
FavouriteLoadouts?: IFavouriteLoadout[];
}