2024-06-06 16:55:37 +02:00
|
|
|
import { Request } from "express";
|
|
|
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
|
|
|
import { getInventory } from "@/src/services/inventoryService";
|
2025-03-03 05:46:16 -08:00
|
|
|
import { Guild, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
2025-01-03 22:17:34 +01:00
|
|
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
2025-03-06 21:24:25 -08:00
|
|
|
import {
|
|
|
|
IDojoClient,
|
|
|
|
IDojoComponentClient,
|
|
|
|
IDojoContributable,
|
|
|
|
IDojoDecoClient,
|
|
|
|
IGuildVault
|
|
|
|
} from "@/src/types/guildTypes";
|
2025-02-11 20:11:31 -08:00
|
|
|
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
2025-03-03 12:48:39 -08:00
|
|
|
import { Types } from "mongoose";
|
2025-03-05 23:54:47 -08:00
|
|
|
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
2025-03-06 07:19:01 -08:00
|
|
|
import { logger } from "../utils/logger";
|
2024-06-06 16:55:37 +02:00
|
|
|
|
2025-02-11 20:11:31 -08:00
|
|
|
export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
|
2024-06-06 16:55:37 +02:00
|
|
|
const accountId = await getAccountIdForRequest(req);
|
|
|
|
const inventory = await getInventory(accountId);
|
2025-01-03 09:06:50 +01:00
|
|
|
return await getGuildForRequestEx(req, inventory);
|
|
|
|
};
|
|
|
|
|
2025-02-11 20:11:31 -08:00
|
|
|
export const getGuildForRequestEx = async (
|
|
|
|
req: Request,
|
|
|
|
inventory: TInventoryDatabaseDocument
|
|
|
|
): Promise<TGuildDatabaseDocument> => {
|
2024-06-06 16:55:37 +02:00
|
|
|
const guildId = req.query.guildId as string;
|
|
|
|
if (!inventory.GuildId || inventory.GuildId.toString() != guildId) {
|
|
|
|
throw new Error("Account is not in the guild that it has sent a request for");
|
|
|
|
}
|
|
|
|
const guild = await Guild.findOne({ _id: guildId });
|
|
|
|
if (!guild) {
|
2025-01-03 09:06:50 +01:00
|
|
|
throw new Error("Account thinks it is in a guild that doesn't exist");
|
2024-06-06 16:55:37 +02:00
|
|
|
}
|
|
|
|
return guild;
|
|
|
|
};
|
2025-02-11 20:11:31 -08:00
|
|
|
|
2025-03-06 21:24:25 -08:00
|
|
|
export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
|
|
|
|
return {
|
|
|
|
DojoRefundRegularCredits: guild.VaultRegularCredits,
|
|
|
|
DojoRefundMiscItems: guild.VaultMiscItems,
|
|
|
|
DojoRefundPremiumCredits: guild.VaultPremiumCredits,
|
|
|
|
ShipDecorations: guild.VaultShipDecorations,
|
|
|
|
FusionTreasures: guild.VaultFusionTreasures
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2025-03-06 07:19:01 -08:00
|
|
|
export const getDojoClient = async (
|
2025-03-03 12:48:39 -08:00
|
|
|
guild: TGuildDatabaseDocument,
|
|
|
|
status: number,
|
2025-03-05 23:54:47 -08:00
|
|
|
componentId: Types.ObjectId | string | undefined = undefined
|
2025-03-06 07:19:01 -08:00
|
|
|
): Promise<IDojoClient> => {
|
2025-02-11 20:11:31 -08:00
|
|
|
const dojo: IDojoClient = {
|
|
|
|
_id: { $oid: guild._id.toString() },
|
|
|
|
Name: guild.Name,
|
|
|
|
Tier: 1,
|
|
|
|
FixedContributions: true,
|
|
|
|
DojoRevision: 1,
|
2025-03-06 21:24:25 -08:00
|
|
|
Vault: getGuildVault(guild),
|
2025-02-11 20:11:31 -08:00
|
|
|
RevisionTime: Math.round(Date.now() / 1000),
|
|
|
|
Energy: guild.DojoEnergy,
|
|
|
|
Capacity: guild.DojoCapacity,
|
|
|
|
DojoRequestStatus: status,
|
|
|
|
DojoComponents: []
|
|
|
|
};
|
2025-03-06 07:19:01 -08:00
|
|
|
const roomsToRemove: Types.ObjectId[] = [];
|
2025-03-03 05:46:16 -08:00
|
|
|
guild.DojoComponents.forEach(dojoComponent => {
|
2025-03-05 23:54:47 -08:00
|
|
|
if (!componentId || dojoComponent._id.equals(componentId)) {
|
2025-03-03 12:48:39 -08:00
|
|
|
const clientComponent: IDojoComponentClient = {
|
|
|
|
id: toOid(dojoComponent._id),
|
|
|
|
pf: dojoComponent.pf,
|
|
|
|
ppf: dojoComponent.ppf,
|
|
|
|
Name: dojoComponent.Name,
|
|
|
|
Message: dojoComponent.Message,
|
2025-03-05 23:54:47 -08:00
|
|
|
DecoCapacity: dojoComponent.DecoCapacity ?? 600
|
2025-03-03 12:48:39 -08:00
|
|
|
};
|
|
|
|
if (dojoComponent.pi) {
|
|
|
|
clientComponent.pi = toOid(dojoComponent.pi);
|
|
|
|
clientComponent.op = dojoComponent.op!;
|
|
|
|
clientComponent.pp = dojoComponent.pp!;
|
|
|
|
}
|
|
|
|
if (dojoComponent.CompletionTime) {
|
|
|
|
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
|
2025-03-06 07:19:01 -08:00
|
|
|
if (dojoComponent.DestructionTime) {
|
|
|
|
if (Date.now() >= dojoComponent.DestructionTime.getTime()) {
|
|
|
|
roomsToRemove.push(dojoComponent._id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
clientComponent.DestructionTime = toMongoDate(dojoComponent.DestructionTime);
|
|
|
|
}
|
2025-03-03 12:48:39 -08:00
|
|
|
} else {
|
|
|
|
clientComponent.RegularCredits = dojoComponent.RegularCredits;
|
|
|
|
clientComponent.MiscItems = dojoComponent.MiscItems;
|
|
|
|
}
|
2025-03-05 23:54:47 -08:00
|
|
|
if (dojoComponent.Decos) {
|
|
|
|
clientComponent.Decos = [];
|
|
|
|
for (const deco of dojoComponent.Decos) {
|
2025-03-06 21:24:25 -08:00
|
|
|
const clientDeco: IDojoDecoClient = {
|
2025-03-05 23:54:47 -08:00
|
|
|
id: toOid(deco._id),
|
|
|
|
Type: deco.Type,
|
|
|
|
Pos: deco.Pos,
|
|
|
|
Rot: deco.Rot,
|
2025-03-06 21:24:25 -08:00
|
|
|
Name: deco.Name
|
|
|
|
};
|
|
|
|
if (deco.CompletionTime) {
|
|
|
|
clientDeco.CompletionTime = toMongoDate(deco.CompletionTime);
|
|
|
|
} else {
|
|
|
|
clientDeco.RegularCredits = deco.RegularCredits;
|
|
|
|
clientDeco.MiscItems = deco.MiscItems;
|
|
|
|
}
|
|
|
|
clientComponent.Decos.push(clientDeco);
|
2025-03-05 23:54:47 -08:00
|
|
|
}
|
|
|
|
}
|
2025-03-03 12:48:39 -08:00
|
|
|
dojo.DojoComponents.push(clientComponent);
|
2025-02-11 20:11:31 -08:00
|
|
|
}
|
|
|
|
});
|
2025-03-06 07:19:01 -08:00
|
|
|
if (roomsToRemove.length) {
|
|
|
|
logger.debug(`removing now-destroyed rooms`, roomsToRemove);
|
|
|
|
for (const id of roomsToRemove) {
|
|
|
|
removeDojoRoom(guild, id);
|
|
|
|
}
|
|
|
|
await guild.save();
|
|
|
|
}
|
2025-02-11 20:11:31 -08:00
|
|
|
return dojo;
|
|
|
|
};
|
2025-03-03 12:48:39 -08:00
|
|
|
|
|
|
|
export const scaleRequiredCount = (count: number): number => {
|
|
|
|
// The recipes in the export are for Moon clans. For now we'll just assume we only have Ghost clans.
|
|
|
|
return Math.max(1, Math.trunc(count / 100));
|
|
|
|
};
|
2025-03-05 23:54:47 -08:00
|
|
|
|
2025-03-06 07:19:01 -08:00
|
|
|
export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types.ObjectId | string): void => {
|
2025-03-05 23:54:47 -08:00
|
|
|
const component = guild.DojoComponents.splice(
|
|
|
|
guild.DojoComponents.findIndex(x => x._id.equals(componentId)),
|
|
|
|
1
|
|
|
|
)[0];
|
|
|
|
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf);
|
|
|
|
if (meta) {
|
|
|
|
guild.DojoCapacity -= meta.capacity;
|
|
|
|
guild.DojoEnergy -= meta.energy;
|
|
|
|
}
|
2025-03-06 21:24:25 -08:00
|
|
|
moveResourcesToVault(guild, component);
|
|
|
|
component.Decos?.forEach(deco => moveResourcesToVault(guild, deco));
|
2025-03-05 23:54:47 -08:00
|
|
|
};
|
|
|
|
|
2025-03-06 07:19:01 -08:00
|
|
|
export const removeDojoDeco = (
|
|
|
|
guild: TGuildDatabaseDocument,
|
|
|
|
componentId: Types.ObjectId | string,
|
|
|
|
decoId: Types.ObjectId | string
|
|
|
|
): void => {
|
2025-03-05 23:54:47 -08:00
|
|
|
const component = guild.DojoComponents.id(componentId)!;
|
|
|
|
const deco = component.Decos!.splice(
|
|
|
|
component.Decos!.findIndex(x => x._id.equals(decoId)),
|
|
|
|
1
|
|
|
|
)[0];
|
|
|
|
const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type);
|
|
|
|
if (meta && meta.capacityCost) {
|
|
|
|
component.DecoCapacity! += meta.capacityCost;
|
|
|
|
}
|
2025-03-06 21:24:25 -08:00
|
|
|
moveResourcesToVault(guild, deco);
|
|
|
|
};
|
|
|
|
|
|
|
|
const moveResourcesToVault = (guild: TGuildDatabaseDocument, component: IDojoContributable): void => {
|
|
|
|
if (component.RegularCredits) {
|
|
|
|
guild.VaultRegularCredits ??= 0;
|
|
|
|
guild.VaultRegularCredits += component.RegularCredits;
|
|
|
|
}
|
|
|
|
if (component.MiscItems) {
|
|
|
|
guild.VaultMiscItems ??= [];
|
|
|
|
for (const componentMiscItem of component.MiscItems) {
|
|
|
|
const vaultMiscItem = guild.VaultMiscItems.find(x => x.ItemType == componentMiscItem.ItemType);
|
|
|
|
if (vaultMiscItem) {
|
|
|
|
vaultMiscItem.ItemCount += componentMiscItem.ItemCount;
|
|
|
|
} else {
|
|
|
|
guild.VaultMiscItems.push(componentMiscItem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (component.RushPlatinum) {
|
|
|
|
guild.VaultPremiumCredits ??= 0;
|
|
|
|
guild.VaultPremiumCredits += component.RushPlatinum;
|
|
|
|
}
|
2025-03-05 23:54:47 -08:00
|
|
|
};
|