From 61062e433f41be18460e254be7d79c70698aec3d Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Fri, 4 Apr 2025 06:02:40 -0700 Subject: [PATCH] feat: personal decos in dojo & move dojo decos (#1451) Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1451 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- package-lock.json | 8 +- package.json | 2 +- .../api/contributeToVaultController.ts | 14 ++-- .../api/placeDecoInComponentController.ts | 53 +++++++++---- src/models/guildModel.ts | 5 +- src/models/personalRoomsModel.ts | 2 +- src/services/guildService.ts | 78 ++++++++++++++++--- src/services/shipCustomizationsService.ts | 14 ++++ src/types/guildTypes.ts | 3 + src/types/shipTypes.ts | 4 +- 10 files changed, 140 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0be5183e..890754cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "morgan": "^1.10.0", "ncp": "^2.0.0", "typescript": ">=5.5 <5.6.0", - "warframe-public-export-plus": "^0.5.49", + "warframe-public-export-plus": "^0.5.50", "warframe-riven-info": "^0.1.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" @@ -3789,9 +3789,9 @@ } }, "node_modules/warframe-public-export-plus": { - "version": "0.5.49", - "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.49.tgz", - "integrity": "sha512-11HA8qEMhFfl12W2qIjjk7fhas+/5G2yXbrOEb8FRZby6tWka0CyUnB6tLT+PCqBEIoU+kwhz0g7CLh3Zmy7Pw==" + "version": "0.5.50", + "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.50.tgz", + "integrity": "sha512-KlhdY/Q5sRAIn/RhmdviKBoX3gk+Jtuen0cWnFB2zqK7eKYMDtd79bKOtTPtnK9zCNzh6gFug2wEeDVam3Bwlw==" }, "node_modules/warframe-riven-info": { "version": "0.1.2", diff --git a/package.json b/package.json index e0eb4c8f..36bf7738 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "morgan": "^1.10.0", "ncp": "^2.0.0", "typescript": ">=5.5 <5.6.0", - "warframe-public-export-plus": "^0.5.49", + "warframe-public-export-plus": "^0.5.50", "warframe-riven-info": "^0.1.2", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" diff --git a/src/controllers/api/contributeToVaultController.ts b/src/controllers/api/contributeToVaultController.ts index fc03e2ca..507d1aa7 100644 --- a/src/controllers/api/contributeToVaultController.ts +++ b/src/controllers/api/contributeToVaultController.ts @@ -1,7 +1,10 @@ import { Alliance, GuildMember } from "@/src/models/guildModel"; import { addGuildMemberMiscItemContribution, + addGuildMemberShipDecoContribution, + addVaultFusionTreasures, addVaultMiscItems, + addVaultShipDecos, getGuildForRequestEx } from "@/src/services/guildService"; import { @@ -51,26 +54,21 @@ export const contributeToVaultController: RequestHandler = async (req, res) => { } if (request.MiscItems.length) { addVaultMiscItems(guild, request.MiscItems); - for (const item of request.MiscItems) { addGuildMemberMiscItemContribution(guildMember, item); - addMiscItems(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]); } } if (request.ShipDecorations.length) { - guild.VaultShipDecorations ??= []; - guildMember.ShipDecorationsContributed ??= []; + addVaultShipDecos(guild, request.ShipDecorations); for (const item of request.ShipDecorations) { - guild.VaultShipDecorations.push(item); - guildMember.ShipDecorationsContributed.push(item); + addGuildMemberShipDecoContribution(guildMember, item); addShipDecorations(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]); } } if (request.FusionTreasures.length) { - guild.VaultFusionTreasures ??= []; + addVaultFusionTreasures(guild, request.FusionTreasures); for (const item of request.FusionTreasures) { - guild.VaultFusionTreasures.push(item); addFusionTreasures(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]); } } diff --git a/src/controllers/api/placeDecoInComponentController.ts b/src/controllers/api/placeDecoInComponentController.ts index 3a09ddfc..deaefc06 100644 --- a/src/controllers/api/placeDecoInComponentController.ts +++ b/src/controllers/api/placeDecoInComponentController.ts @@ -12,7 +12,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService"; import { GuildPermission } from "@/src/types/guildTypes"; import { RequestHandler } from "express"; import { Types } from "mongoose"; -import { ExportDojoRecipes } from "warframe-public-export-plus"; +import { ExportDojoRecipes, ExportResources } from "warframe-public-export-plus"; export const placeDecoInComponentController: RequestHandler = async (req, res) => { const accountId = await getAccountIdForRequest(req); @@ -32,23 +32,37 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) = } component.Decos ??= []; - const deco = - component.Decos[ - component.Decos.push({ - _id: new Types.ObjectId(), - Type: request.Type, - Pos: request.Pos, - Rot: request.Rot, - Name: request.Name - }) - 1 - ]; - - const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == request.Type); - if (meta) { - if (meta.capacityCost) { - component.DecoCapacity -= meta.capacityCost; + if (request.MoveId) { + const deco = component.Decos.find(x => x._id.equals(request.MoveId))!; + deco.Pos = request.Pos; + deco.Rot = request.Rot; + } else { + const deco = + component.Decos[ + component.Decos.push({ + _id: new Types.ObjectId(), + Type: request.Type, + Pos: request.Pos, + Rot: request.Rot, + Name: request.Name, + Sockets: request.Sockets + }) - 1 + ]; + const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == request.Type); + if (meta) { + if (meta.capacityCost) { + component.DecoCapacity -= meta.capacityCost; + } + } else { + const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0]; + if (deco.Sockets !== undefined) { + guild.VaultFusionTreasures!.find(x => x.ItemType == itemType && x.Sockets == deco.Sockets)!.ItemCount -= + 1; + } else { + guild.VaultShipDecorations!.find(x => x.ItemType == itemType)!.ItemCount -= 1; + } } - if (meta.price == 0 && meta.ingredients.length == 0) { + if (!meta || (meta.price == 0 && meta.ingredients.length == 0)) { deco.CompletionTime = new Date(); } else if (guild.AutoContributeFromVault && guild.VaultRegularCredits && guild.VaultMiscItems) { if (guild.VaultRegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) { @@ -94,4 +108,9 @@ interface IPlaceDecoInComponentRequest { Pos: number[]; Rot: number[]; Name?: string; + Sockets?: number; + Scale?: number; // only provided alongside MoveId and seems to always be 1 + MoveId?: string; + ShipDeco?: boolean; + VaultDeco?: boolean; } diff --git a/src/models/guildModel.ts b/src/models/guildModel.ts index 763e6241..fad1e0e8 100644 --- a/src/models/guildModel.ts +++ b/src/models/guildModel.ts @@ -17,16 +17,19 @@ import { } from "@/src/types/guildTypes"; import { Document, Model, model, Schema, Types } from "mongoose"; import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel"; +import { pictureFrameInfoSchema } from "./personalRoomsModel"; const dojoDecoSchema = new Schema({ Type: String, Pos: [Number], Rot: [Number], Name: String, + Sockets: Number, RegularCredits: Number, MiscItems: { type: [typeCountSchema], default: undefined }, CompletionTime: Date, - RushPlatinum: Number + RushPlatinum: Number, + PictureFrameInfo: pictureFrameInfoSchema }); const dojoLeaderboardEntrySchema = new Schema( diff --git a/src/models/personalRoomsModel.ts b/src/models/personalRoomsModel.ts index b8049d6f..1c6a7c6d 100644 --- a/src/models/personalRoomsModel.ts +++ b/src/models/personalRoomsModel.ts @@ -12,7 +12,7 @@ import { } from "@/src/types/shipTypes"; import { Schema, model } from "mongoose"; -const pictureFrameInfoSchema = new Schema( +export const pictureFrameInfoSchema = new Schema( { Image: String, Filter: String, diff --git a/src/services/guildService.ts b/src/services/guildService.ts index bb646b46..0e05bb94 100644 --- a/src/services/guildService.ts +++ b/src/services/guildService.ts @@ -21,13 +21,13 @@ import { } from "@/src/types/guildTypes"; import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers"; import { Types } from "mongoose"; -import { ExportDojoRecipes, IDojoBuild, IDojoResearch } from "warframe-public-export-plus"; +import { ExportDojoRecipes, ExportResources, IDojoBuild, IDojoResearch } from "warframe-public-export-plus"; import { logger } from "../utils/logger"; import { config } from "./configService"; import { Account } from "../models/loginModel"; import { getRandomInt } from "./rngService"; import { Inbox } from "../models/inboxModel"; -import { ITypeCount } from "../types/inventoryTypes/inventoryTypes"; +import { IFusionTreasure, ITypeCount } from "../types/inventoryTypes/inventoryTypes"; import { IInventoryChanges } from "../types/purchaseTypes"; export const getGuildForRequest = async (req: Request): Promise => { @@ -202,7 +202,9 @@ export const getDojoClient = async ( Type: deco.Type, Pos: deco.Pos, Rot: deco.Rot, - Name: deco.Name + Name: deco.Name, + Sockets: deco.Sockets, + PictureFrameInfo: deco.PictureFrameInfo }; if (deco.CompletionTime) { clientDeco.CompletionTime = toMongoDate(deco.CompletionTime); @@ -285,8 +287,28 @@ export const removeDojoDeco = ( 1 )[0]; const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type); - if (meta && meta.capacityCost) { - component.DecoCapacity! += meta.capacityCost; + if (meta) { + if (meta.capacityCost) { + component.DecoCapacity! += meta.capacityCost; + } + } else { + const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0]; + if (deco.Sockets !== undefined) { + addVaultFusionTreasures(guild, [ + { + ItemType: itemType, + ItemCount: 1, + Sockets: deco.Sockets + } + ]); + } else { + addVaultShipDecos(guild, [ + { + ItemType: itemType, + ItemCount: 1 + } + ]); + } } moveResourcesToVault(guild, deco); }; @@ -311,12 +333,38 @@ export const getVaultMiscItemCount = (guild: TGuildDatabaseDocument, itemType: s export const addVaultMiscItems = (guild: TGuildDatabaseDocument, miscItems: ITypeCount[]): void => { guild.VaultMiscItems ??= []; - for (const miscItem of miscItems) { - const vaultMiscItem = guild.VaultMiscItems.find(x => x.ItemType == miscItem.ItemType); - if (vaultMiscItem) { - vaultMiscItem.ItemCount += miscItem.ItemCount; + for (const item of miscItems) { + const vaultItem = guild.VaultMiscItems.find(x => x.ItemType == item.ItemType); + if (vaultItem) { + vaultItem.ItemCount += item.ItemCount; } else { - guild.VaultMiscItems.push(miscItem); + guild.VaultMiscItems.push(item); + } + } +}; + +export const addVaultShipDecos = (guild: TGuildDatabaseDocument, shipDecos: ITypeCount[]): void => { + guild.VaultShipDecorations ??= []; + for (const item of shipDecos) { + const vaultItem = guild.VaultShipDecorations.find(x => x.ItemType == item.ItemType); + if (vaultItem) { + vaultItem.ItemCount += item.ItemCount; + } else { + guild.VaultShipDecorations.push(item); + } + } +}; + +export const addVaultFusionTreasures = (guild: TGuildDatabaseDocument, fusionTreasures: IFusionTreasure[]): void => { + guild.VaultFusionTreasures ??= []; + for (const item of fusionTreasures) { + const vaultItem = guild.VaultFusionTreasures.find( + x => x.ItemType == item.ItemType && x.Sockets == item.Sockets + ); + if (vaultItem) { + vaultItem.ItemCount += item.ItemCount; + } else { + guild.VaultFusionTreasures.push(item); } } }; @@ -331,6 +379,16 @@ export const addGuildMemberMiscItemContribution = (guildMember: IGuildMemberData } }; +export const addGuildMemberShipDecoContribution = (guildMember: IGuildMemberDatabase, item: ITypeCount): void => { + guildMember.ShipDecorationsContributed ??= []; + const shipDecoContribution = guildMember.ShipDecorationsContributed.find(x => x.ItemType == item.ItemType); + if (shipDecoContribution) { + shipDecoContribution.ItemCount += item.ItemCount; + } else { + guildMember.ShipDecorationsContributed.push(item); + } +}; + export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument, build: IDojoBuild): void => { if (build.guildXpValue) { guild.ClaimedXP ??= []; diff --git a/src/services/shipCustomizationsService.ts b/src/services/shipCustomizationsService.ts index 20c3d4ca..47764917 100644 --- a/src/services/shipCustomizationsService.ts +++ b/src/services/shipCustomizationsService.ts @@ -10,6 +10,9 @@ import { logger } from "@/src/utils/logger"; import { Types } from "mongoose"; import { addShipDecorations, getInventory } from "./inventoryService"; import { config } from "./configService"; +import { Guild } from "../models/guildModel"; +import { hasGuildPermission } from "./guildService"; +import { GuildPermission } from "../types/guildTypes"; export const setShipCustomizations = async ( accountId: string, @@ -154,6 +157,17 @@ export const handleSetShipDecorations = async ( }; export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlacedDecoInfoRequest): Promise => { + if (req.GuildId && req.ComponentId) { + const guild = (await Guild.findById(req.GuildId))!; + if (await hasGuildPermission(guild, accountId, GuildPermission.Decorator)) { + const component = guild.DojoComponents.id(req.ComponentId)!; + const deco = component.Decos!.find(x => x._id.equals(req.DecoId))!; + deco.PictureFrameInfo = req.PictureFrameInfo; + await guild.save(); + } + return; + } + const personalRooms = await getPersonalRooms(accountId); const room = personalRooms.Ship.Rooms.find(room => room.Name === req.Room); diff --git a/src/types/guildTypes.ts b/src/types/guildTypes.ts index d40c605c..949f87ce 100644 --- a/src/types/guildTypes.ts +++ b/src/types/guildTypes.ts @@ -1,6 +1,7 @@ import { Types } from "mongoose"; import { IOid, IMongoDate } from "@/src/types/commonTypes"; import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes"; +import { IPictureFrameInfo } from "./shipTypes"; export interface IGuildClient { _id: IOid; @@ -191,10 +192,12 @@ export interface IDojoDecoClient { Pos: number[]; Rot: number[]; Name?: string; // for teleporters + Sockets?: number; RegularCredits?: number; MiscItems?: IMiscItem[]; CompletionTime?: IMongoDate; RushPlatinum?: number; + PictureFrameInfo?: IPictureFrameInfo; } export interface IDojoDecoDatabase extends Omit { diff --git a/src/types/shipTypes.ts b/src/types/shipTypes.ts index 936a5cc6..23c46c48 100644 --- a/src/types/shipTypes.ts +++ b/src/types/shipTypes.ts @@ -127,7 +127,9 @@ export interface ISetPlacedDecoInfoRequest { DecoId: string; Room: string; PictureFrameInfo: IPictureFrameInfo; - BootLocation: string; + BootLocation?: string; + ComponentId?: string; + GuildId?: string; } export interface IPictureFrameInfo {