2025-03-05 23:54:47 -08:00
import { TGuildDatabaseDocument } from "@/src/models/guildModel" ;
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel" ;
2025-03-03 12:48:39 -08:00
import { getDojoClient , getGuildForRequestEx , scaleRequiredCount } from "@/src/services/guildService" ;
import { addMiscItems , getInventory , updateCurrency } from "@/src/services/inventoryService" ;
import { getAccountIdForRequest } from "@/src/services/loginService" ;
2025-03-05 23:54:47 -08:00
import { IDojoContributable } from "@/src/types/guildTypes" ;
2025-03-03 12:48:39 -08:00
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes" ;
import { IInventoryChanges } from "@/src/types/purchaseTypes" ;
import { RequestHandler } from "express" ;
2025-03-05 23:54:47 -08:00
import { ExportDojoRecipes , IDojoRecipe } from "warframe-public-export-plus" ;
interface IContributeToDojoComponentRequest {
ComponentId : string ;
DecoId? : string ;
DecoType? : string ;
IngredientContributions : {
ItemType : string ;
ItemCount : number ;
} [ ] ;
RegularCredits : number ;
VaultIngredientContributions : [ ] ;
VaultCredits : number ;
}
2025-03-03 12:48:39 -08:00
export const contributeToDojoComponentController : RequestHandler = async ( req , res ) = > {
const accountId = await getAccountIdForRequest ( req ) ;
const inventory = await getInventory ( accountId ) ;
const guild = await getGuildForRequestEx ( req , inventory ) ;
2025-03-04 08:34:42 +01:00
// Any clan member should have permission to contribute although notably permission is denied if they have not crafted the dojo key and were simply invited in.
2025-03-03 12:48:39 -08:00
const request = JSON . parse ( String ( req . body ) ) as IContributeToDojoComponentRequest ;
const component = guild . DojoComponents . id ( request . ComponentId ) ! ;
2025-03-05 23:54:47 -08:00
const inventoryChanges : IInventoryChanges = { } ;
if ( ! component . CompletionTime ) {
// Room is in "Collecting Materials" state
if ( request . DecoId ) {
throw new Error ( "attempt to contribute to a deco in an unfinished room?!" ) ;
}
const meta = Object . values ( ExportDojoRecipes . rooms ) . find ( x = > x . resultType == component . pf ) ! ;
await processContribution ( guild , request , inventory , inventoryChanges , meta , component ) ;
} else {
// Room is past "Collecting Materials"
if ( request . DecoId ) {
const deco = component . Decos ! . find ( x = > x . _id . equals ( request . DecoId ) ) ! ;
const meta = Object . values ( ExportDojoRecipes . decos ) . find ( x = > x . resultType == deco . Type ) ! ;
await processContribution ( guild , request , inventory , inventoryChanges , meta , deco ) ;
}
}
await guild . save ( ) ;
await inventory . save ( ) ;
res . json ( {
. . . getDojoClient ( guild , 0 , component . _id ) ,
InventoryChanges : inventoryChanges
} ) ;
} ;
const processContribution = async (
guild : TGuildDatabaseDocument ,
request : IContributeToDojoComponentRequest ,
inventory : TInventoryDatabaseDocument ,
inventoryChanges : IInventoryChanges ,
meta : IDojoRecipe ,
component : IDojoContributable
) : Promise < void > = > {
2025-03-03 12:48:39 -08:00
component . RegularCredits ? ? = 0 ;
2025-03-05 23:54:47 -08:00
if ( component . RegularCredits + request . RegularCredits > scaleRequiredCount ( meta . price ) ) {
request . RegularCredits = scaleRequiredCount ( meta . price ) - component . RegularCredits ;
2025-03-03 12:48:39 -08:00
}
component . RegularCredits += request . RegularCredits ;
2025-03-05 23:54:47 -08:00
inventoryChanges . RegularCredits = - request . RegularCredits ;
updateCurrency ( inventory , request . RegularCredits , false ) ;
2025-03-03 12:48:39 -08:00
component . MiscItems ? ? = [ ] ;
const miscItemChanges : IMiscItem [ ] = [ ] ;
for ( const ingredientContribution of request . IngredientContributions ) {
const componentMiscItem = component . MiscItems . find ( x = > x . ItemType == ingredientContribution . ItemType ) ;
if ( componentMiscItem ) {
2025-03-05 23:54:47 -08:00
const ingredientMeta = meta . ingredients . find ( x = > x . ItemType == ingredientContribution . ItemType ) ! ;
2025-03-03 12:48:39 -08:00
if (
componentMiscItem . ItemCount + ingredientContribution . ItemCount >
scaleRequiredCount ( ingredientMeta . ItemCount )
) {
ingredientContribution . ItemCount =
scaleRequiredCount ( ingredientMeta . ItemCount ) - componentMiscItem . ItemCount ;
}
componentMiscItem . ItemCount += ingredientContribution . ItemCount ;
} else {
component . MiscItems . push ( ingredientContribution ) ;
}
miscItemChanges . push ( {
ItemType : ingredientContribution.ItemType ,
ItemCount : ingredientContribution.ItemCount * - 1
} ) ;
}
addMiscItems ( inventory , miscItemChanges ) ;
inventoryChanges . MiscItems = miscItemChanges ;
2025-03-05 23:54:47 -08:00
if ( component . RegularCredits >= scaleRequiredCount ( meta . price ) ) {
2025-03-03 12:48:39 -08:00
let fullyFunded = true ;
2025-03-05 23:54:47 -08:00
for ( const ingredient of meta . ingredients ) {
2025-03-03 12:48:39 -08:00
const componentMiscItem = component . MiscItems . find ( x = > x . ItemType == ingredient . ItemType ) ;
if ( ! componentMiscItem || componentMiscItem . ItemCount < scaleRequiredCount ( ingredient . ItemCount ) ) {
fullyFunded = false ;
break ;
}
}
if ( fullyFunded ) {
2025-03-05 23:54:47 -08:00
if ( request . IngredientContributions . length ) {
// We've already updated subpaths of MiscItems, we need to allow MongoDB to save this before we remove MiscItems.
await guild . save ( ) ;
}
2025-03-03 12:48:39 -08:00
component . RegularCredits = undefined ;
component . MiscItems = undefined ;
2025-03-05 23:54:47 -08:00
component . CompletionTime = new Date ( Date . now ( ) + meta . time * 1000 ) ;
2025-03-03 12:48:39 -08:00
}
}
} ;