forked from OpenWF/SpaceNinjaServer
		
	chore: avoid using client oid representation in database (#2685)
Reviewed-on: OpenWF/SpaceNinjaServer#2685 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									2c43d897c0
								
							
						
					
					
						commit
						dfd1fb834b
					
				@ -1,4 +1,4 @@
 | 
			
		||||
import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { fromDbOid, version_compare } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import {
 | 
			
		||||
    antivirusMods,
 | 
			
		||||
    decodeNemesisGuess,
 | 
			
		||||
@ -130,7 +130,9 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
			
		||||
            if (result1 == GUESS_CORRECT || result2 == GUESS_CORRECT || result3 == GUESS_CORRECT) {
 | 
			
		||||
                let antivirusGain = 5;
 | 
			
		||||
                const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
			
		||||
                const dataknifeLoadout = loadout.DATAKNIFE.id(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid);
 | 
			
		||||
                const dataknifeLoadout = loadout.DATAKNIFE.id(
 | 
			
		||||
                    fromDbOid(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE])
 | 
			
		||||
                );
 | 
			
		||||
                const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
			
		||||
                const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
			
		||||
                for (const upgrade of body.knife!.AttachedUpgrades) {
 | 
			
		||||
@ -219,7 +221,7 @@ export const nemesisController: RequestHandler = async (req, res) => {
 | 
			
		||||
                    // Subtract a charge from all requiem mods installed on parazon
 | 
			
		||||
                    const loadout = (await Loadout.findById(inventory.LoadOutPresets, "DATAKNIFE"))!;
 | 
			
		||||
                    const dataknifeLoadout = loadout.DATAKNIFE.id(
 | 
			
		||||
                        inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE].$oid
 | 
			
		||||
                        fromDbOid(inventory.CurrentLoadOutIds[LoadoutIndex.DATAKNIFE])
 | 
			
		||||
                    );
 | 
			
		||||
                    const dataknifeConfigIndex = dataknifeLoadout?.s?.mod ?? 0;
 | 
			
		||||
                    const dataknifeUpgrades = inventory.DataKnives[0].Configs[dataknifeConfigIndex].Upgrades!;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { fromDbOid, toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { Guild, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
 | 
			
		||||
import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
			
		||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
			
		||||
@ -13,7 +13,8 @@ import {
 | 
			
		||||
    IDailyAffiliations,
 | 
			
		||||
    IMission,
 | 
			
		||||
    IPlayerSkills,
 | 
			
		||||
    ITypeXPItem
 | 
			
		||||
    ITypeXPItem,
 | 
			
		||||
    LoadoutIndex
 | 
			
		||||
} from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { catBreadHash, getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
@ -298,30 +299,32 @@ const populateLoadout = async (
 | 
			
		||||
): Promise<void> => {
 | 
			
		||||
    if (inventory.CurrentLoadOutIds.length) {
 | 
			
		||||
        const loadout = (await Loadout.findById(inventory.LoadOutPresets, "NORMAL"))!;
 | 
			
		||||
        result.LoadOutPreset = loadout.NORMAL.id(inventory.CurrentLoadOutIds[0].$oid)!.toJSON<ILoadoutConfigClient>();
 | 
			
		||||
        result.LoadOutPreset = loadout.NORMAL.id(
 | 
			
		||||
            fromDbOid(inventory.CurrentLoadOutIds[LoadoutIndex.NORMAL])
 | 
			
		||||
        )!.toJSON<ILoadoutConfigClient>();
 | 
			
		||||
        result.LoadOutPreset.ItemId = undefined;
 | 
			
		||||
        const skins = new Set<string>();
 | 
			
		||||
        if (result.LoadOutPreset.s) {
 | 
			
		||||
        if (result.LoadOutPreset.s?.ItemId) {
 | 
			
		||||
            result.LoadOutInventory.Suits = [
 | 
			
		||||
                inventory.Suits.id(result.LoadOutPreset.s.ItemId.$oid)!.toJSON<IEquipmentClient>()
 | 
			
		||||
                inventory.Suits.id(fromDbOid(result.LoadOutPreset.s.ItemId))!.toJSON<IEquipmentClient>()
 | 
			
		||||
            ];
 | 
			
		||||
            resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.Suits[0]);
 | 
			
		||||
        }
 | 
			
		||||
        if (result.LoadOutPreset.p) {
 | 
			
		||||
        if (result.LoadOutPreset.p?.ItemId) {
 | 
			
		||||
            result.LoadOutInventory.Pistols = [
 | 
			
		||||
                inventory.Pistols.id(result.LoadOutPreset.p.ItemId.$oid)!.toJSON<IEquipmentClient>()
 | 
			
		||||
                inventory.Pistols.id(fromDbOid(result.LoadOutPreset.p.ItemId))!.toJSON<IEquipmentClient>()
 | 
			
		||||
            ];
 | 
			
		||||
            resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.Pistols[0]);
 | 
			
		||||
        }
 | 
			
		||||
        if (result.LoadOutPreset.l) {
 | 
			
		||||
        if (result.LoadOutPreset.l?.ItemId) {
 | 
			
		||||
            result.LoadOutInventory.LongGuns = [
 | 
			
		||||
                inventory.LongGuns.id(result.LoadOutPreset.l.ItemId.$oid)!.toJSON<IEquipmentClient>()
 | 
			
		||||
                inventory.LongGuns.id(fromDbOid(result.LoadOutPreset.l.ItemId))!.toJSON<IEquipmentClient>()
 | 
			
		||||
            ];
 | 
			
		||||
            resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.LongGuns[0]);
 | 
			
		||||
        }
 | 
			
		||||
        if (result.LoadOutPreset.m) {
 | 
			
		||||
        if (result.LoadOutPreset.m?.ItemId) {
 | 
			
		||||
            result.LoadOutInventory.Melee = [
 | 
			
		||||
                inventory.Melee.id(result.LoadOutPreset.m.ItemId.$oid)!.toJSON<IEquipmentClient>()
 | 
			
		||||
                inventory.Melee.id(fromDbOid(result.LoadOutPreset.m.ItemId))!.toJSON<IEquipmentClient>()
 | 
			
		||||
            ];
 | 
			
		||||
            resolveAndCollectSkins(inventory, skins, result.LoadOutInventory.Melee[0]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,11 @@ export const fromOid = (oid: IOidWithLegacySupport): string => {
 | 
			
		||||
    return (oid.$oid ?? oid.$id)!;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// For oids that may have been stored incorrectly
 | 
			
		||||
export const fromDbOid = (x: Types.ObjectId | IOid): Types.ObjectId => {
 | 
			
		||||
    return "$oid" in x ? new Types.ObjectId(x.$oid) : x;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const toMongoDate = (date: Date): IMongoDate => {
 | 
			
		||||
    return { $date: { $numberLong: date.getTime().toString() } };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -100,8 +100,8 @@ import {
 | 
			
		||||
    IOperatorConfigDatabase,
 | 
			
		||||
    IPolarity
 | 
			
		||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { EquipmentSelectionSchema, oidSchema } from "@/src/models/inventoryModels/loadoutModel";
 | 
			
		||||
import { fromDbOid, toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { EquipmentSelectionSchema } from "@/src/models/inventoryModels/loadoutModel";
 | 
			
		||||
import { ICountedStoreItem } from "warframe-public-export-plus";
 | 
			
		||||
import { colorSchema, shipCustomizationSchema } from "@/src/models/commonModel";
 | 
			
		||||
import {
 | 
			
		||||
@ -109,8 +109,8 @@ import {
 | 
			
		||||
    ICrewShipMemberClient,
 | 
			
		||||
    ICrewShipMemberDatabase,
 | 
			
		||||
    ICrewShipMembersDatabase,
 | 
			
		||||
    ICrewShipWeapon,
 | 
			
		||||
    ICrewShipWeaponEmplacements,
 | 
			
		||||
    ICrewShipWeaponDatabase,
 | 
			
		||||
    ICrewShipWeaponEmplacementsDatabase,
 | 
			
		||||
    IEquipmentClient,
 | 
			
		||||
    IEquipmentDatabase,
 | 
			
		||||
    IKubrowPetDetailsClient,
 | 
			
		||||
@ -847,7 +847,6 @@ const endlessXpProgressSchema = new Schema<IEndlessXpProgressDatabase>(
 | 
			
		||||
    },
 | 
			
		||||
    { _id: false }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
endlessXpProgressSchema.set("toJSON", {
 | 
			
		||||
    transform(_doc, ret: Record<string, any>) {
 | 
			
		||||
        const db = ret as IEndlessXpProgressDatabase;
 | 
			
		||||
@ -861,7 +860,8 @@ endlessXpProgressSchema.set("toJSON", {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
const crewShipWeaponEmplacementsSchema = new Schema<ICrewShipWeaponEmplacements>(
 | 
			
		||||
 | 
			
		||||
const crewShipWeaponEmplacementsSchema = new Schema<ICrewShipWeaponEmplacementsDatabase>(
 | 
			
		||||
    {
 | 
			
		||||
        PRIMARY_A: EquipmentSelectionSchema,
 | 
			
		||||
        PRIMARY_B: EquipmentSelectionSchema,
 | 
			
		||||
@ -871,7 +871,7 @@ const crewShipWeaponEmplacementsSchema = new Schema<ICrewShipWeaponEmplacements>
 | 
			
		||||
    { _id: false }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const crewShipWeaponSchema = new Schema<ICrewShipWeapon>(
 | 
			
		||||
const crewShipWeaponSchema = new Schema<ICrewShipWeaponDatabase>(
 | 
			
		||||
    {
 | 
			
		||||
        PILOT: crewShipWeaponEmplacementsSchema,
 | 
			
		||||
        PORT_GUNS: crewShipWeaponEmplacementsSchema,
 | 
			
		||||
@ -1748,7 +1748,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
			
		||||
        HasContributedToDojo: Boolean,
 | 
			
		||||
        HWIDProtectEnabled: Boolean,
 | 
			
		||||
        LoadOutPresets: { type: Schema.Types.ObjectId, ref: "Loadout" },
 | 
			
		||||
        CurrentLoadOutIds: [oidSchema],
 | 
			
		||||
        CurrentLoadOutIds: [Schema.Types.Mixed], // should be Types.ObjectId[] but might be IOid[] because of old commits
 | 
			
		||||
        RandomUpgradesIdentified: Number,
 | 
			
		||||
        BountyScore: Number,
 | 
			
		||||
        //ChallengeInstanceStates: [Schema.Types.Mixed],
 | 
			
		||||
@ -1808,12 +1808,15 @@ inventorySchema.set("toJSON", {
 | 
			
		||||
        const inventoryDatabase = returnedObject as Partial<IInventoryDatabase>;
 | 
			
		||||
        const inventoryResponse = returnedObject as IInventoryClient;
 | 
			
		||||
 | 
			
		||||
        if (inventoryDatabase.TrainingDate) {
 | 
			
		||||
            inventoryResponse.TrainingDate = toMongoDate(inventoryDatabase.TrainingDate);
 | 
			
		||||
        }
 | 
			
		||||
        if (inventoryDatabase.Created) {
 | 
			
		||||
            inventoryResponse.Created = toMongoDate(inventoryDatabase.Created);
 | 
			
		||||
        }
 | 
			
		||||
        if (inventoryDatabase.CurrentLoadOutIds) {
 | 
			
		||||
            inventoryResponse.CurrentLoadOutIds = inventoryDatabase.CurrentLoadOutIds.map(x => toOid(fromDbOid(x)));
 | 
			
		||||
        }
 | 
			
		||||
        if (inventoryDatabase.TrainingDate) {
 | 
			
		||||
            inventoryResponse.TrainingDate = toMongoDate(inventoryDatabase.TrainingDate);
 | 
			
		||||
        }
 | 
			
		||||
        if (inventoryDatabase.GuildId) {
 | 
			
		||||
            inventoryResponse.GuildId = toOid(inventoryDatabase.GuildId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,13 @@
 | 
			
		||||
import { fromDbOid, toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { IEquipmentSelection } from "@/src/types/equipmentTypes";
 | 
			
		||||
import { IEquipmentSelectionClient, IEquipmentSelectionDatabase } from "@/src/types/equipmentTypes";
 | 
			
		||||
import { ILoadoutConfigDatabase, ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
 | 
			
		||||
import { Document, Model, Schema, Types, model } from "mongoose";
 | 
			
		||||
 | 
			
		||||
export const oidSchema = new Schema<IOid>(
 | 
			
		||||
    {
 | 
			
		||||
        $oid: String
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        _id: false
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
//create a mongoose schema based on interface M
 | 
			
		||||
export const EquipmentSelectionSchema = new Schema<IEquipmentSelection>(
 | 
			
		||||
export const EquipmentSelectionSchema = new Schema<IEquipmentSelectionDatabase>(
 | 
			
		||||
    {
 | 
			
		||||
        ItemId: oidSchema,
 | 
			
		||||
        ItemId: Schema.Types.Mixed, // should be Types.ObjectId but might be IOid because of old commits
 | 
			
		||||
        mod: Number,
 | 
			
		||||
        cus: Number,
 | 
			
		||||
        hide: Boolean
 | 
			
		||||
@ -24,6 +16,17 @@ export const EquipmentSelectionSchema = new Schema<IEquipmentSelection>(
 | 
			
		||||
        _id: false
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
EquipmentSelectionSchema.set("toJSON", {
 | 
			
		||||
    virtuals: true,
 | 
			
		||||
    transform(_doc, ret: Record<string, any>) {
 | 
			
		||||
        const db = ret as IEquipmentSelectionDatabase;
 | 
			
		||||
        const client = ret as IEquipmentSelectionClient;
 | 
			
		||||
 | 
			
		||||
        if (db.ItemId) {
 | 
			
		||||
            client.ItemId = toOid(fromDbOid(db.ItemId));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -39,8 +39,14 @@ import {
 | 
			
		||||
    ICrewShipMemberDatabase,
 | 
			
		||||
    ICrewShipMembersClient,
 | 
			
		||||
    ICrewShipMembersDatabase,
 | 
			
		||||
    ICrewShipWeaponClient,
 | 
			
		||||
    ICrewShipWeaponDatabase,
 | 
			
		||||
    ICrewShipWeaponEmplacementsClient,
 | 
			
		||||
    ICrewShipWeaponEmplacementsDatabase,
 | 
			
		||||
    IEquipmentClient,
 | 
			
		||||
    IEquipmentDatabase,
 | 
			
		||||
    IEquipmentSelectionClient,
 | 
			
		||||
    IEquipmentSelectionDatabase,
 | 
			
		||||
    IKubrowPetDetailsClient,
 | 
			
		||||
    IKubrowPetDetailsDatabase
 | 
			
		||||
} from "@/src/types/equipmentTypes";
 | 
			
		||||
@ -84,7 +90,8 @@ const convertEquipment = (client: IEquipmentClient): IEquipmentDatabase => {
 | 
			
		||||
        Expiry: convertOptionalDate(client.Expiry),
 | 
			
		||||
        UpgradesExpiry: convertOptionalDate(client.UpgradesExpiry),
 | 
			
		||||
        UmbraDate: convertOptionalDate(client.UmbraDate),
 | 
			
		||||
        CrewMembers: client.CrewMembers ? convertCrewShipMembers(client.CrewMembers) : undefined,
 | 
			
		||||
        Weapon: client.Weapon ? importCrewShipWeapon(client.Weapon) : undefined,
 | 
			
		||||
        CrewMembers: client.CrewMembers ? importCrewShipMembers(client.CrewMembers) : undefined,
 | 
			
		||||
        Details: client.Details ? convertKubrowDetails(client.Details) : undefined,
 | 
			
		||||
        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
 | 
			
		||||
        Configs: client.Configs
 | 
			
		||||
@ -133,14 +140,43 @@ const replaceSlots = (db: ISlots, client: ISlots): void => {
 | 
			
		||||
    db.Slots = client.Slots;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const importCrewMemberId = (crewMemberId: ICrewShipMemberClient): ICrewShipMemberDatabase => {
 | 
			
		||||
const convertEquipmentSelection = (es: IEquipmentSelectionClient): IEquipmentSelectionDatabase => {
 | 
			
		||||
    const { ItemId, ...rest } = es;
 | 
			
		||||
    return {
 | 
			
		||||
        ...rest,
 | 
			
		||||
        ItemId: ItemId ? new Types.ObjectId(ItemId.$oid) : undefined
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const convertCrewShipWeaponEmplacements = (
 | 
			
		||||
    obj: ICrewShipWeaponEmplacementsClient
 | 
			
		||||
): ICrewShipWeaponEmplacementsDatabase => {
 | 
			
		||||
    return {
 | 
			
		||||
        PRIMARY_A: obj.PRIMARY_A ? convertEquipmentSelection(obj.PRIMARY_A) : undefined,
 | 
			
		||||
        PRIMARY_B: obj.PRIMARY_B ? convertEquipmentSelection(obj.PRIMARY_B) : undefined,
 | 
			
		||||
        SECONDARY_A: obj.SECONDARY_A ? convertEquipmentSelection(obj.SECONDARY_A) : undefined,
 | 
			
		||||
        SECONDARY_B: obj.SECONDARY_B ? convertEquipmentSelection(obj.SECONDARY_B) : undefined
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const importCrewShipWeapon = (weapon: ICrewShipWeaponClient): ICrewShipWeaponDatabase => {
 | 
			
		||||
    return {
 | 
			
		||||
        PILOT: weapon.PILOT ? convertCrewShipWeaponEmplacements(weapon.PILOT) : undefined,
 | 
			
		||||
        PORT_GUNS: weapon.PORT_GUNS ? convertCrewShipWeaponEmplacements(weapon.PORT_GUNS) : undefined,
 | 
			
		||||
        STARBOARD_GUNS: weapon.STARBOARD_GUNS ? convertCrewShipWeaponEmplacements(weapon.STARBOARD_GUNS) : undefined,
 | 
			
		||||
        ARTILLERY: weapon.ARTILLERY ? convertCrewShipWeaponEmplacements(weapon.ARTILLERY) : undefined,
 | 
			
		||||
        SCANNER: weapon.SCANNER ? convertCrewShipWeaponEmplacements(weapon.SCANNER) : undefined
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const importCrewMemberId = (crewMemberId: ICrewShipMemberClient): ICrewShipMemberDatabase => {
 | 
			
		||||
    if (crewMemberId.ItemId) {
 | 
			
		||||
        return { ItemId: new Types.ObjectId(crewMemberId.ItemId.$oid) };
 | 
			
		||||
    }
 | 
			
		||||
    return { NemesisFingerprint: BigInt(crewMemberId.NemesisFingerprint ?? 0) };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const convertCrewShipMembers = (client: ICrewShipMembersClient): ICrewShipMembersDatabase => {
 | 
			
		||||
export const importCrewShipMembers = (client: ICrewShipMembersClient): ICrewShipMembersDatabase => {
 | 
			
		||||
    return {
 | 
			
		||||
        SLOT_A: client.SLOT_A ? importCrewMemberId(client.SLOT_A) : undefined,
 | 
			
		||||
        SLOT_B: client.SLOT_B ? importCrewMemberId(client.SLOT_B) : undefined,
 | 
			
		||||
@ -429,34 +465,40 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const convertLoadOutConfig = (client: ILoadoutConfigClient): ILoadoutConfigDatabase => {
 | 
			
		||||
export const importLoadOutConfig = (client: ILoadoutConfigClient): ILoadoutConfigDatabase => {
 | 
			
		||||
    const { ItemId, ...rest } = client;
 | 
			
		||||
    return {
 | 
			
		||||
        ...rest,
 | 
			
		||||
        _id: new Types.ObjectId(ItemId.$oid)
 | 
			
		||||
        _id: new Types.ObjectId(ItemId.$oid),
 | 
			
		||||
        s: client.s ? convertEquipmentSelection(client.s) : undefined,
 | 
			
		||||
        p: client.p ? convertEquipmentSelection(client.p) : undefined,
 | 
			
		||||
        l: client.l ? convertEquipmentSelection(client.l) : undefined,
 | 
			
		||||
        m: client.m ? convertEquipmentSelection(client.m) : undefined,
 | 
			
		||||
        h: client.h ? convertEquipmentSelection(client.h) : undefined,
 | 
			
		||||
        a: client.a ? convertEquipmentSelection(client.a) : undefined
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPresets): void => {
 | 
			
		||||
    db.NORMAL = client.NORMAL.map(convertLoadOutConfig);
 | 
			
		||||
    db.SENTINEL = client.SENTINEL.map(convertLoadOutConfig);
 | 
			
		||||
    db.ARCHWING = client.ARCHWING.map(convertLoadOutConfig);
 | 
			
		||||
    db.NORMAL_PVP = client.NORMAL_PVP.map(convertLoadOutConfig);
 | 
			
		||||
    db.LUNARO = client.LUNARO.map(convertLoadOutConfig);
 | 
			
		||||
    db.OPERATOR = client.OPERATOR.map(convertLoadOutConfig);
 | 
			
		||||
    db.GEAR = client.GEAR?.map(convertLoadOutConfig);
 | 
			
		||||
    db.KDRIVE = client.KDRIVE.map(convertLoadOutConfig);
 | 
			
		||||
    db.DATAKNIFE = client.DATAKNIFE.map(convertLoadOutConfig);
 | 
			
		||||
    db.MECH = client.MECH.map(convertLoadOutConfig);
 | 
			
		||||
    db.OPERATOR_ADULT = client.OPERATOR_ADULT.map(convertLoadOutConfig);
 | 
			
		||||
    db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig);
 | 
			
		||||
    db.NORMAL = client.NORMAL.map(importLoadOutConfig);
 | 
			
		||||
    db.SENTINEL = client.SENTINEL.map(importLoadOutConfig);
 | 
			
		||||
    db.ARCHWING = client.ARCHWING.map(importLoadOutConfig);
 | 
			
		||||
    db.NORMAL_PVP = client.NORMAL_PVP.map(importLoadOutConfig);
 | 
			
		||||
    db.LUNARO = client.LUNARO.map(importLoadOutConfig);
 | 
			
		||||
    db.OPERATOR = client.OPERATOR.map(importLoadOutConfig);
 | 
			
		||||
    db.GEAR = client.GEAR?.map(importLoadOutConfig);
 | 
			
		||||
    db.KDRIVE = client.KDRIVE.map(importLoadOutConfig);
 | 
			
		||||
    db.DATAKNIFE = client.DATAKNIFE.map(importLoadOutConfig);
 | 
			
		||||
    db.MECH = client.MECH.map(importLoadOutConfig);
 | 
			
		||||
    db.OPERATOR_ADULT = client.OPERATOR_ADULT.map(importLoadOutConfig);
 | 
			
		||||
    db.DRIFTER = client.DRIFTER.map(importLoadOutConfig);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const convertCustomizationInfo = (client: ICustomizationInfoClient): ICustomizationInfoDatabase => {
 | 
			
		||||
    return {
 | 
			
		||||
        ...client,
 | 
			
		||||
        LoadOutPreset: client.LoadOutPreset ? convertLoadOutConfig(client.LoadOutPreset) : undefined,
 | 
			
		||||
        VehiclePreset: client.VehiclePreset ? convertLoadOutConfig(client.VehiclePreset) : undefined
 | 
			
		||||
        LoadOutPreset: client.LoadOutPreset ? importLoadOutConfig(client.LoadOutPreset) : undefined,
 | 
			
		||||
        VehiclePreset: client.VehiclePreset ? importLoadOutConfig(client.VehiclePreset) : undefined
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -63,6 +63,7 @@ import {
 | 
			
		||||
import { createShip } from "@/src/services/shipService";
 | 
			
		||||
import {
 | 
			
		||||
    catbrowDetails,
 | 
			
		||||
    fromDbOid,
 | 
			
		||||
    fromMongoDate,
 | 
			
		||||
    fromOid,
 | 
			
		||||
    kubrowDetails,
 | 
			
		||||
@ -2232,6 +2233,8 @@ export const setupKahlSyndicate = (inventory: TInventoryDatabaseDocument): void
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void => {
 | 
			
		||||
    inventory.CurrentLoadOutIds = inventory.CurrentLoadOutIds.map(fromDbOid);
 | 
			
		||||
 | 
			
		||||
    let index = inventory.MiscItems.findIndex(x => x.ItemType == "");
 | 
			
		||||
    if (index != -1) {
 | 
			
		||||
        inventory.MiscItems.splice(index, 1);
 | 
			
		||||
 | 
			
		||||
@ -65,7 +65,6 @@ import {
 | 
			
		||||
    getNemesisPasscode
 | 
			
		||||
} from "@/src/helpers/nemesisHelpers";
 | 
			
		||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
 | 
			
		||||
import { ILoadoutConfigDatabase } from "@/src/types/saveLoadoutTypes";
 | 
			
		||||
import {
 | 
			
		||||
    getLiteSortie,
 | 
			
		||||
    getSortie,
 | 
			
		||||
@ -84,6 +83,7 @@ import { ITypeCount } from "@/src/types/commonTypes";
 | 
			
		||||
import { IEquipmentClient } from "@/src/types/equipmentTypes";
 | 
			
		||||
import { Guild } from "@/src/models/guildModel";
 | 
			
		||||
import { handleGuildGoalProgress } from "@/src/services/guildService";
 | 
			
		||||
import { importLoadOutConfig } from "@/src/services/importService";
 | 
			
		||||
 | 
			
		||||
const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
 | 
			
		||||
    // Disruption missions just tell us (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2599)
 | 
			
		||||
@ -602,11 +602,7 @@ export const addMissionInventoryUpdates = async (
 | 
			
		||||
                    const loadout = await Loadout.findOne({ loadoutOwnerId: inventory.accountOwnerId });
 | 
			
		||||
                    if (loadout) {
 | 
			
		||||
                        for (const [loadoutId, loadoutConfig] of Object.entries(value.LoadOuts.NORMAL)) {
 | 
			
		||||
                            const { ItemId, ...loadoutConfigItemIdRemoved } = loadoutConfig;
 | 
			
		||||
                            const loadoutConfigDatabase: ILoadoutConfigDatabase = {
 | 
			
		||||
                                _id: new Types.ObjectId(ItemId.$oid),
 | 
			
		||||
                                ...loadoutConfigItemIdRemoved
 | 
			
		||||
                            };
 | 
			
		||||
                            const loadoutConfigDatabase = importLoadOutConfig(loadoutConfig);
 | 
			
		||||
                            const dbConfig = loadout.NORMAL.id(loadoutId);
 | 
			
		||||
                            if (dbConfig) {
 | 
			
		||||
                                dbConfig.overwrite(loadoutConfigDatabase);
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@ import {
 | 
			
		||||
    IItemEntry,
 | 
			
		||||
    ILoadoutClient,
 | 
			
		||||
    ILoadoutEntry,
 | 
			
		||||
    ILoadoutConfigDatabase,
 | 
			
		||||
    IOperatorConfigEntry,
 | 
			
		||||
    ISaveLoadoutRequestNoUpgradeVer
 | 
			
		||||
} from "@/src/types/saveLoadoutTypes";
 | 
			
		||||
@ -14,7 +13,7 @@ import { isEmptyObject } from "@/src/helpers/general";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { IItemConfig } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import { importCrewMemberId } from "@/src/services/importService";
 | 
			
		||||
import { importCrewShipMembers, importCrewShipWeapon, importLoadOutConfig } from "@/src/services/importService";
 | 
			
		||||
 | 
			
		||||
//TODO: setup default items on account creation or like originally in giveStartingItems.php
 | 
			
		||||
 | 
			
		||||
@ -88,20 +87,17 @@ export const handleInventoryItemConfigChange = async (
 | 
			
		||||
 | 
			
		||||
                        const oldLoadoutConfig = loadout[loadoutSlot].id(loadoutId);
 | 
			
		||||
 | 
			
		||||
                        const { ItemId, ...loadoutConfigItemIdRemoved } = loadoutConfig;
 | 
			
		||||
                        const loadoutConfigDatabase: ILoadoutConfigDatabase = {
 | 
			
		||||
                            _id: new Types.ObjectId(ItemId.$oid),
 | 
			
		||||
                            ...loadoutConfigItemIdRemoved
 | 
			
		||||
                        };
 | 
			
		||||
                        const loadoutConfigDatabase = importLoadOutConfig(loadoutConfig);
 | 
			
		||||
 | 
			
		||||
                        // if no config with this id exists, create a new one
 | 
			
		||||
                        if (!oldLoadoutConfig) {
 | 
			
		||||
                            //save the new object id and assign it for every ffff return at the end
 | 
			
		||||
                            if (ItemId.$oid === "ffffffffffffffffffffffff") {
 | 
			
		||||
                            if (loadoutConfigDatabase._id.toString() === "ffffffffffffffffffffffff") {
 | 
			
		||||
                                if (!newLoadoutId) {
 | 
			
		||||
                                    newLoadoutId = new Types.ObjectId();
 | 
			
		||||
                                }
 | 
			
		||||
                                loadout[loadoutSlot].push({ _id: newLoadoutId, ...loadoutConfigItemIdRemoved });
 | 
			
		||||
                                loadoutConfigDatabase._id = newLoadoutId;
 | 
			
		||||
                                loadout[loadoutSlot].push(loadoutConfigDatabase);
 | 
			
		||||
                                continue;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
@ -218,15 +214,11 @@ export const handleInventoryItemConfigChange = async (
 | 
			
		||||
                        if ("Customization" in itemConfigEntries) {
 | 
			
		||||
                            inventoryItem.Customization = itemConfigEntries.Customization;
 | 
			
		||||
                        }
 | 
			
		||||
                        if ("Weapon" in itemConfigEntries) {
 | 
			
		||||
                            inventoryItem.Weapon = itemConfigEntries.Weapon;
 | 
			
		||||
                        if (itemConfigEntries.Weapon) {
 | 
			
		||||
                            inventoryItem.Weapon = importCrewShipWeapon(itemConfigEntries.Weapon);
 | 
			
		||||
                        }
 | 
			
		||||
                        if (itemConfigEntries.CrewMembers) {
 | 
			
		||||
                            inventoryItem.CrewMembers = {
 | 
			
		||||
                                SLOT_A: importCrewMemberId(itemConfigEntries.CrewMembers.SLOT_A ?? {}),
 | 
			
		||||
                                SLOT_B: importCrewMemberId(itemConfigEntries.CrewMembers.SLOT_B ?? {}),
 | 
			
		||||
                                SLOT_C: importCrewMemberId(itemConfigEntries.CrewMembers.SLOT_C ?? {})
 | 
			
		||||
                            };
 | 
			
		||||
                            inventoryItem.CrewMembers = importCrewShipMembers(itemConfigEntries.CrewMembers);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
@ -7,14 +7,18 @@ import {
 | 
			
		||||
    IPolarity
 | 
			
		||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
 | 
			
		||||
export interface IEquipmentSelection {
 | 
			
		||||
    ItemId: IOid;
 | 
			
		||||
export interface IEquipmentSelectionClient {
 | 
			
		||||
    ItemId?: IOid;
 | 
			
		||||
    mod?: number;
 | 
			
		||||
    cus?: number;
 | 
			
		||||
    ItemType?: string;
 | 
			
		||||
    hide?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IEquipmentSelectionDatabase extends Omit<IEquipmentSelectionClient, "ItemId"> {
 | 
			
		||||
    ItemId?: Types.ObjectId | IOid; // should be Types.ObjectId but might be IOid because of old commits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum EquipmentFeatures {
 | 
			
		||||
    DOUBLE_CAPACITY = 1,
 | 
			
		||||
    UTILITY_SLOT = 2,
 | 
			
		||||
@ -51,7 +55,7 @@ export interface IEquipmentDatabase {
 | 
			
		||||
    UpgradesExpiry?: Date;
 | 
			
		||||
    UmbraDate?: Date; // related to scrapped "echoes of umbra" feature
 | 
			
		||||
    ArchonCrystalUpgrades?: IArchonCrystalUpgrade[];
 | 
			
		||||
    Weapon?: ICrewShipWeapon;
 | 
			
		||||
    Weapon?: ICrewShipWeaponDatabase;
 | 
			
		||||
    Customization?: ICrewShipCustomization;
 | 
			
		||||
    RailjackImage?: IFlavourItem;
 | 
			
		||||
    CrewMembers?: ICrewShipMembersDatabase;
 | 
			
		||||
@ -64,13 +68,14 @@ export interface IEquipmentDatabase {
 | 
			
		||||
export interface IEquipmentClient
 | 
			
		||||
    extends Omit<
 | 
			
		||||
        IEquipmentDatabase,
 | 
			
		||||
        "_id" | "InfestationDate" | "Expiry" | "UpgradesExpiry" | "UmbraDate" | "CrewMembers" | "Details"
 | 
			
		||||
        "_id" | "InfestationDate" | "Expiry" | "UpgradesExpiry" | "UmbraDate" | "Weapon" | "CrewMembers" | "Details"
 | 
			
		||||
    > {
 | 
			
		||||
    ItemId: IOidWithLegacySupport;
 | 
			
		||||
    InfestationDate?: IMongoDate;
 | 
			
		||||
    Expiry?: IMongoDate;
 | 
			
		||||
    UpgradesExpiry?: IMongoDate;
 | 
			
		||||
    UmbraDate?: IMongoDate;
 | 
			
		||||
    Weapon?: ICrewShipWeaponClient;
 | 
			
		||||
    CrewMembers?: ICrewShipMembersClient;
 | 
			
		||||
    Details?: IKubrowPetDetailsClient;
 | 
			
		||||
}
 | 
			
		||||
@ -117,19 +122,34 @@ export enum Status {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// inventory.CrewShips[0].Weapon
 | 
			
		||||
export interface ICrewShipWeapon {
 | 
			
		||||
    PILOT?: ICrewShipWeaponEmplacements;
 | 
			
		||||
    PORT_GUNS?: ICrewShipWeaponEmplacements;
 | 
			
		||||
    STARBOARD_GUNS?: ICrewShipWeaponEmplacements;
 | 
			
		||||
    ARTILLERY?: ICrewShipWeaponEmplacements;
 | 
			
		||||
    SCANNER?: ICrewShipWeaponEmplacements;
 | 
			
		||||
export interface ICrewShipWeaponClient {
 | 
			
		||||
    PILOT?: ICrewShipWeaponEmplacementsClient;
 | 
			
		||||
    PORT_GUNS?: ICrewShipWeaponEmplacementsClient;
 | 
			
		||||
    STARBOARD_GUNS?: ICrewShipWeaponEmplacementsClient;
 | 
			
		||||
    ARTILLERY?: ICrewShipWeaponEmplacementsClient;
 | 
			
		||||
    SCANNER?: ICrewShipWeaponEmplacementsClient;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ICrewShipWeaponEmplacements {
 | 
			
		||||
    PRIMARY_A?: IEquipmentSelection;
 | 
			
		||||
    PRIMARY_B?: IEquipmentSelection;
 | 
			
		||||
    SECONDARY_A?: IEquipmentSelection;
 | 
			
		||||
    SECONDARY_B?: IEquipmentSelection;
 | 
			
		||||
export interface ICrewShipWeaponDatabase {
 | 
			
		||||
    PILOT?: ICrewShipWeaponEmplacementsDatabase;
 | 
			
		||||
    PORT_GUNS?: ICrewShipWeaponEmplacementsDatabase;
 | 
			
		||||
    STARBOARD_GUNS?: ICrewShipWeaponEmplacementsDatabase;
 | 
			
		||||
    ARTILLERY?: ICrewShipWeaponEmplacementsDatabase;
 | 
			
		||||
    SCANNER?: ICrewShipWeaponEmplacementsDatabase;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ICrewShipWeaponEmplacementsClient {
 | 
			
		||||
    PRIMARY_A?: IEquipmentSelectionClient;
 | 
			
		||||
    PRIMARY_B?: IEquipmentSelectionClient;
 | 
			
		||||
    SECONDARY_A?: IEquipmentSelectionClient;
 | 
			
		||||
    SECONDARY_B?: IEquipmentSelectionClient;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ICrewShipWeaponEmplacementsDatabase {
 | 
			
		||||
    PRIMARY_A?: IEquipmentSelectionDatabase;
 | 
			
		||||
    PRIMARY_B?: IEquipmentSelectionDatabase;
 | 
			
		||||
    SECONDARY_A?: IEquipmentSelectionDatabase;
 | 
			
		||||
    SECONDARY_B?: IEquipmentSelectionDatabase;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ICrewShipMembersClient {
 | 
			
		||||
 | 
			
		||||
@ -68,12 +68,14 @@ export interface IInventoryDatabase
 | 
			
		||||
            | "LastInventorySync"
 | 
			
		||||
            | "EndlessXP"
 | 
			
		||||
            | "PersonalGoalProgress"
 | 
			
		||||
            | "CurrentLoadOutIds"
 | 
			
		||||
            | TEquipmentKey
 | 
			
		||||
        >,
 | 
			
		||||
        InventoryDatabaseEquipment,
 | 
			
		||||
        IAccountCheats {
 | 
			
		||||
    accountOwnerId: Types.ObjectId;
 | 
			
		||||
    Created: Date;
 | 
			
		||||
    CurrentLoadOutIds: Types.ObjectId[] | IOid[]; // should be Types.ObjectId[] but might be IOid[] because of old commits
 | 
			
		||||
    TrainingDate: Date;
 | 
			
		||||
    LoadOutPresets: Types.ObjectId; // LoadOutPresets changed from ILoadOutPresets to Types.ObjectId for population
 | 
			
		||||
    //Mailbox?: IMailboxDatabase;
 | 
			
		||||
@ -254,7 +256,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
			
		||||
    ActiveQuest: string;
 | 
			
		||||
    FlavourItems: IFlavourItem[];
 | 
			
		||||
    LoadOutPresets: ILoadOutPresets;
 | 
			
		||||
    CurrentLoadOutIds: IOid[]; // we store it in the database using this representation as well :/
 | 
			
		||||
    CurrentLoadOutIds: IOid[];
 | 
			
		||||
    Missions: IMission[];
 | 
			
		||||
    RandomUpgradesIdentified?: number;
 | 
			
		||||
    LastRegionPlayed: TSolarMapRegion;
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,12 @@ import {
 | 
			
		||||
    IOperatorConfigClient
 | 
			
		||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { ICrewShipMembersClient, ICrewShipWeapon, IEquipmentSelection } from "@/src/types/equipmentTypes";
 | 
			
		||||
import {
 | 
			
		||||
    ICrewShipMembersClient,
 | 
			
		||||
    ICrewShipWeaponClient,
 | 
			
		||||
    IEquipmentSelectionClient,
 | 
			
		||||
    IEquipmentSelectionDatabase
 | 
			
		||||
} from "@/src/types/equipmentTypes";
 | 
			
		||||
 | 
			
		||||
export interface ISaveLoadoutRequest {
 | 
			
		||||
    LoadOuts: ILoadoutClient;
 | 
			
		||||
@ -53,10 +58,12 @@ export interface IOperatorConfigEntry {
 | 
			
		||||
    [configId: string]: IOperatorConfigClient;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// client
 | 
			
		||||
export interface IItemEntry {
 | 
			
		||||
    [itemId: string]: IConfigEntry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// client
 | 
			
		||||
export type IConfigEntry = {
 | 
			
		||||
    [configId in "0" | "1" | "2" | "3" | "4" | "5"]: IItemConfig;
 | 
			
		||||
} & {
 | 
			
		||||
@ -66,7 +73,7 @@ export type IConfigEntry = {
 | 
			
		||||
    ItemName?: string;
 | 
			
		||||
    RailjackImage?: IFlavourItem;
 | 
			
		||||
    Customization?: ICrewShipCustomization;
 | 
			
		||||
    Weapon?: ICrewShipWeapon;
 | 
			
		||||
    Weapon?: ICrewShipWeaponClient;
 | 
			
		||||
    CrewMembers?: ICrewShipMembersClient;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -108,10 +115,6 @@ export interface ILoadoutEntry {
 | 
			
		||||
    [key: string]: ILoadoutConfigClient;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ILoadoutConfigDatabase extends Omit<ILoadoutConfigClient, "ItemId"> {
 | 
			
		||||
    _id: Types.ObjectId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum FocusSchool {
 | 
			
		||||
    Attack = "AP_ATTACK",
 | 
			
		||||
    Defense = "AP_DEFENSE",
 | 
			
		||||
@ -125,12 +128,23 @@ export interface ILoadoutConfigClient {
 | 
			
		||||
    PresetIcon?: string;
 | 
			
		||||
    Favorite?: boolean;
 | 
			
		||||
    n?: string; // Loadout name
 | 
			
		||||
    s?: IEquipmentSelection; // Suit
 | 
			
		||||
    p?: IEquipmentSelection; // Secondary weapon
 | 
			
		||||
    l?: IEquipmentSelection; // Primary weapon
 | 
			
		||||
    m?: IEquipmentSelection; // Melee weapon
 | 
			
		||||
    h?: IEquipmentSelection; // Gravimag weapon
 | 
			
		||||
    a?: IEquipmentSelection; // Necromech exalted weapon
 | 
			
		||||
    s?: IEquipmentSelectionClient; // Suit
 | 
			
		||||
    p?: IEquipmentSelectionClient; // Secondary weapon
 | 
			
		||||
    l?: IEquipmentSelectionClient; // Primary weapon
 | 
			
		||||
    m?: IEquipmentSelectionClient; // Melee weapon
 | 
			
		||||
    h?: IEquipmentSelectionClient; // Gravimag weapon
 | 
			
		||||
    a?: IEquipmentSelectionClient; // Necromech exalted weapon
 | 
			
		||||
    ItemId: IOid;
 | 
			
		||||
    Remove?: boolean; // when client wants to remove a config, it only includes ItemId & Remove.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ILoadoutConfigDatabase
 | 
			
		||||
    extends Omit<ILoadoutConfigClient, "ItemId" | "s" | "p" | "l" | "m" | "h" | "a"> {
 | 
			
		||||
    _id: Types.ObjectId;
 | 
			
		||||
    s?: IEquipmentSelectionDatabase;
 | 
			
		||||
    p?: IEquipmentSelectionDatabase;
 | 
			
		||||
    l?: IEquipmentSelectionDatabase;
 | 
			
		||||
    m?: IEquipmentSelectionDatabase;
 | 
			
		||||
    h?: IEquipmentSelectionDatabase;
 | 
			
		||||
    a?: IEquipmentSelectionDatabase;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user