forked from OpenWF/SpaceNinjaServer
		
	Reviewed-on: OpenWF/SpaceNinjaServer#1401 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
		
			
				
	
	
		
			169 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
 | 
						|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
						|
import {
 | 
						|
    addGuildMemberMiscItemContribution,
 | 
						|
    getDojoClient,
 | 
						|
    getGuildForRequestEx,
 | 
						|
    hasAccessToDojo,
 | 
						|
    processDojoBuildMaterialsGathered,
 | 
						|
    scaleRequiredCount,
 | 
						|
    setDojoRoomLogFunded
 | 
						|
} from "@/src/services/guildService";
 | 
						|
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
 | 
						|
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
						|
import { IDojoContributable, IGuildMemberDatabase } from "@/src/types/guildTypes";
 | 
						|
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
						|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
						|
import { RequestHandler } from "express";
 | 
						|
import { ExportDojoRecipes, IDojoBuild } from "warframe-public-export-plus";
 | 
						|
 | 
						|
interface IContributeToDojoComponentRequest {
 | 
						|
    ComponentId: string;
 | 
						|
    DecoId?: string;
 | 
						|
    DecoType?: string;
 | 
						|
    IngredientContributions: IMiscItem[];
 | 
						|
    RegularCredits: number;
 | 
						|
    VaultIngredientContributions: IMiscItem[];
 | 
						|
    VaultCredits: number;
 | 
						|
}
 | 
						|
 | 
						|
export const contributeToDojoComponentController: RequestHandler = async (req, res) => {
 | 
						|
    const accountId = await getAccountIdForRequest(req);
 | 
						|
    const inventory = await getInventory(accountId);
 | 
						|
    // 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.
 | 
						|
    if (!hasAccessToDojo(inventory)) {
 | 
						|
        res.json({ DojoRequestStatus: -1 });
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    const guild = await getGuildForRequestEx(req, inventory);
 | 
						|
    const guildMember = (await GuildMember.findOne(
 | 
						|
        { accountId, guildId: guild._id },
 | 
						|
        "RegularCreditsContributed MiscItemsContributed"
 | 
						|
    ))!;
 | 
						|
    const request = JSON.parse(String(req.body)) as IContributeToDojoComponentRequest;
 | 
						|
    const component = guild.DojoComponents.id(request.ComponentId)!;
 | 
						|
 | 
						|
    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)!;
 | 
						|
        processContribution(guild, guildMember, request, inventory, inventoryChanges, meta, component);
 | 
						|
        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
 | 
						|
        if (component.CompletionTime) {
 | 
						|
            setDojoRoomLogFunded(guild, 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)!;
 | 
						|
            processContribution(guild, guildMember, request, inventory, inventoryChanges, meta, deco);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    await Promise.all([guild.save(), inventory.save(), guildMember.save()]);
 | 
						|
    res.json({
 | 
						|
        ...(await getDojoClient(guild, 0, component._id)),
 | 
						|
        InventoryChanges: inventoryChanges
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
const processContribution = (
 | 
						|
    guild: TGuildDatabaseDocument,
 | 
						|
    guildMember: IGuildMemberDatabase,
 | 
						|
    request: IContributeToDojoComponentRequest,
 | 
						|
    inventory: TInventoryDatabaseDocument,
 | 
						|
    inventoryChanges: IInventoryChanges,
 | 
						|
    meta: IDojoBuild,
 | 
						|
    component: IDojoContributable
 | 
						|
): void => {
 | 
						|
    component.RegularCredits ??= 0;
 | 
						|
    if (request.RegularCredits) {
 | 
						|
        component.RegularCredits += request.RegularCredits;
 | 
						|
        inventoryChanges.RegularCredits = -request.RegularCredits;
 | 
						|
        updateCurrency(inventory, request.RegularCredits, false);
 | 
						|
 | 
						|
        guildMember.RegularCreditsContributed ??= 0;
 | 
						|
        guildMember.RegularCreditsContributed += request.RegularCredits;
 | 
						|
    }
 | 
						|
    if (request.VaultCredits) {
 | 
						|
        component.RegularCredits += request.VaultCredits;
 | 
						|
        guild.VaultRegularCredits! -= request.VaultCredits;
 | 
						|
    }
 | 
						|
    if (component.RegularCredits > scaleRequiredCount(guild.Tier, meta.price)) {
 | 
						|
        guild.VaultRegularCredits ??= 0;
 | 
						|
        guild.VaultRegularCredits += component.RegularCredits - scaleRequiredCount(guild.Tier, meta.price);
 | 
						|
        component.RegularCredits = scaleRequiredCount(guild.Tier, meta.price);
 | 
						|
    }
 | 
						|
 | 
						|
    component.MiscItems ??= [];
 | 
						|
    if (request.VaultIngredientContributions.length) {
 | 
						|
        for (const ingredientContribution of request.VaultIngredientContributions) {
 | 
						|
            const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredientContribution.ItemType);
 | 
						|
            if (componentMiscItem) {
 | 
						|
                const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
 | 
						|
                if (
 | 
						|
                    componentMiscItem.ItemCount + ingredientContribution.ItemCount >
 | 
						|
                    scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount)
 | 
						|
                ) {
 | 
						|
                    ingredientContribution.ItemCount =
 | 
						|
                        scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
 | 
						|
                }
 | 
						|
                componentMiscItem.ItemCount += ingredientContribution.ItemCount;
 | 
						|
            } else {
 | 
						|
                component.MiscItems.push(ingredientContribution);
 | 
						|
            }
 | 
						|
            const vaultMiscItem = guild.VaultMiscItems!.find(x => x.ItemType == ingredientContribution.ItemType)!;
 | 
						|
            vaultMiscItem.ItemCount -= ingredientContribution.ItemCount;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (request.IngredientContributions.length) {
 | 
						|
        const miscItemChanges: IMiscItem[] = [];
 | 
						|
        for (const ingredientContribution of request.IngredientContributions) {
 | 
						|
            const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredientContribution.ItemType);
 | 
						|
            if (componentMiscItem) {
 | 
						|
                const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
 | 
						|
                if (
 | 
						|
                    componentMiscItem.ItemCount + ingredientContribution.ItemCount >
 | 
						|
                    scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount)
 | 
						|
                ) {
 | 
						|
                    ingredientContribution.ItemCount =
 | 
						|
                        scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
 | 
						|
                }
 | 
						|
                componentMiscItem.ItemCount += ingredientContribution.ItemCount;
 | 
						|
            } else {
 | 
						|
                component.MiscItems.push(ingredientContribution);
 | 
						|
            }
 | 
						|
            miscItemChanges.push({
 | 
						|
                ItemType: ingredientContribution.ItemType,
 | 
						|
                ItemCount: ingredientContribution.ItemCount * -1
 | 
						|
            });
 | 
						|
 | 
						|
            addGuildMemberMiscItemContribution(guildMember, ingredientContribution);
 | 
						|
        }
 | 
						|
        addMiscItems(inventory, miscItemChanges);
 | 
						|
        inventoryChanges.MiscItems = miscItemChanges;
 | 
						|
    }
 | 
						|
 | 
						|
    if (component.RegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) {
 | 
						|
        let fullyFunded = true;
 | 
						|
        for (const ingredient of meta.ingredients) {
 | 
						|
            const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredient.ItemType);
 | 
						|
            if (
 | 
						|
                !componentMiscItem ||
 | 
						|
                componentMiscItem.ItemCount < scaleRequiredCount(guild.Tier, ingredient.ItemCount)
 | 
						|
            ) {
 | 
						|
                fullyFunded = false;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (fullyFunded) {
 | 
						|
            component.CompletionTime = new Date(Date.now() + meta.time * 1000);
 | 
						|
            processDojoBuildMaterialsGathered(guild, meta);
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 |