2023-12-14 17:34:15 +01:00
|
|
|
import {
|
|
|
|
IItemEntry,
|
|
|
|
ILoadoutClient,
|
|
|
|
ILoadoutEntry,
|
2024-05-07 20:38:44 +02:00
|
|
|
ILoadoutConfigDatabase,
|
2023-12-14 17:34:15 +01:00
|
|
|
IOperatorConfigEntry,
|
|
|
|
ISaveLoadoutRequestNoUpgradeVer
|
|
|
|
} from "@/src/types/saveLoadoutTypes";
|
2024-02-18 13:58:43 +01:00
|
|
|
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
2023-12-14 17:34:15 +01:00
|
|
|
import { getInventory } from "@/src/services/inventoryService";
|
|
|
|
import { IOid } from "@/src/types/commonTypes";
|
2023-12-28 16:24:52 +01:00
|
|
|
import { Types } from "mongoose";
|
|
|
|
import { isEmptyObject } from "@/src/helpers/general";
|
2024-01-06 16:26:58 +01:00
|
|
|
import { logger } from "@/src/utils/logger";
|
2025-01-27 13:18:16 +01:00
|
|
|
import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
2023-12-14 17:34:15 +01:00
|
|
|
|
|
|
|
//TODO: setup default items on account creation or like originally in giveStartingItems.php
|
|
|
|
|
|
|
|
//TODO: change update functions to only add and not save perhaps, functions that add and return inventory perhaps
|
|
|
|
|
|
|
|
/* loadouts has loadoutconfigs
|
|
|
|
operatorloadouts has itemconfig, but no multiple config ids
|
|
|
|
itemconfig has multiple config ids
|
|
|
|
*/
|
|
|
|
export const handleInventoryItemConfigChange = async (
|
|
|
|
equipmentChanges: ISaveLoadoutRequestNoUpgradeVer,
|
|
|
|
accountId: string
|
2023-12-28 16:24:52 +01:00
|
|
|
): Promise<string | void> => {
|
2023-12-14 17:34:15 +01:00
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
|
2025-03-29 15:20:54 -07:00
|
|
|
for (const [_equipmentName, equipment] of Object.entries(equipmentChanges)) {
|
2023-12-14 17:34:15 +01:00
|
|
|
const equipmentName = _equipmentName as keyof ISaveLoadoutRequestNoUpgradeVer;
|
|
|
|
|
|
|
|
if (isEmptyObject(equipment)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// non-empty is a change in loadout(or suit...)
|
|
|
|
switch (equipmentName) {
|
2025-01-27 13:18:16 +01:00
|
|
|
case "AdultOperatorLoadOuts":
|
2023-12-14 17:34:15 +01:00
|
|
|
case "OperatorLoadOuts":
|
2025-01-27 13:18:16 +01:00
|
|
|
case "KahlLoadOuts": {
|
2023-12-14 17:34:15 +01:00
|
|
|
const operatorConfig = equipment as IOperatorConfigEntry;
|
|
|
|
const operatorLoadout = inventory[equipmentName];
|
2024-01-06 16:26:58 +01:00
|
|
|
logger.debug(`operator loadout received ${equipmentName} `, operatorConfig);
|
2023-12-14 17:34:15 +01:00
|
|
|
// all non-empty entries are one loadout slot
|
|
|
|
for (const [loadoutId, loadoutConfig] of Object.entries(operatorConfig)) {
|
2024-01-06 16:26:58 +01:00
|
|
|
logger.debug(`loadoutId ${loadoutId} loadoutConfig`, { config: loadoutConfig });
|
2025-01-20 12:21:39 +01:00
|
|
|
const loadout = operatorLoadout.id(loadoutId);
|
2023-12-14 17:34:15 +01:00
|
|
|
|
|
|
|
// if no config with this id exists, create a new one
|
|
|
|
if (!loadout) {
|
|
|
|
const { ItemId, ...loadoutConfigItemIdRemoved } = loadoutConfig;
|
|
|
|
operatorLoadout.push({
|
|
|
|
_id: ItemId.$oid,
|
|
|
|
...loadoutConfigItemIdRemoved
|
|
|
|
});
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
loadout.set(loadoutConfig);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "LoadOuts": {
|
2024-01-06 16:26:58 +01:00
|
|
|
logger.debug("loadout received");
|
2024-02-18 13:58:43 +01:00
|
|
|
const loadout = await Loadout.findOne({ loadoutOwnerId: accountId });
|
2023-12-14 17:34:15 +01:00
|
|
|
if (!loadout) {
|
|
|
|
throw new Error("loadout not found");
|
|
|
|
}
|
|
|
|
|
2023-12-28 16:24:52 +01:00
|
|
|
let newLoadoutId: Types.ObjectId | undefined;
|
2023-12-14 17:34:15 +01:00
|
|
|
for (const [_loadoutSlot, _loadout] of Object.entries(equipment)) {
|
|
|
|
const loadoutSlot = _loadoutSlot as keyof ILoadoutClient;
|
|
|
|
const newLoadout = _loadout as ILoadoutEntry;
|
|
|
|
|
|
|
|
// empty loadout slot like: "NORMAL": {}
|
|
|
|
if (isEmptyObject(newLoadout)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// all non-empty entries are one loadout slot
|
|
|
|
for (const [loadoutId, loadoutConfig] of Object.entries(newLoadout)) {
|
2024-05-04 23:11:55 +02:00
|
|
|
if (loadoutConfig.Remove) {
|
|
|
|
loadout[loadoutSlot].pull({ _id: loadoutId });
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2025-03-31 04:15:32 -07:00
|
|
|
const oldLoadoutConfig = loadout[loadoutSlot].id(loadoutId);
|
2023-12-14 17:34:15 +01:00
|
|
|
|
2024-05-07 20:38:44 +02:00
|
|
|
const { ItemId, ...loadoutConfigItemIdRemoved } = loadoutConfig;
|
|
|
|
const loadoutConfigDatabase: ILoadoutConfigDatabase = {
|
|
|
|
_id: new Types.ObjectId(ItemId.$oid),
|
|
|
|
...loadoutConfigItemIdRemoved
|
|
|
|
};
|
|
|
|
|
2023-12-14 17:34:15 +01:00
|
|
|
// if no config with this id exists, create a new one
|
|
|
|
if (!oldLoadoutConfig) {
|
2023-12-28 16:24:52 +01:00
|
|
|
//save the new object id and assign it for every ffff return at the end
|
|
|
|
if (ItemId.$oid === "ffffffffffffffffffffffff") {
|
|
|
|
if (!newLoadoutId) {
|
|
|
|
newLoadoutId = new Types.ObjectId();
|
|
|
|
}
|
|
|
|
loadout[loadoutSlot].push({ _id: newLoadoutId, ...loadoutConfigItemIdRemoved });
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-05-07 20:38:44 +02:00
|
|
|
loadout[loadoutSlot].push(loadoutConfigDatabase);
|
2023-12-14 17:34:15 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const loadoutIndex = loadout[loadoutSlot].indexOf(oldLoadoutConfig);
|
2025-01-20 12:21:39 +01:00
|
|
|
if (loadoutIndex === -1) {
|
2023-12-14 17:34:15 +01:00
|
|
|
throw new Error("loadout index not found");
|
|
|
|
}
|
|
|
|
|
2024-05-07 20:38:44 +02:00
|
|
|
loadout[loadoutSlot][loadoutIndex].overwrite(loadoutConfigDatabase);
|
2023-12-14 17:34:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
await loadout.save();
|
2023-12-28 16:24:52 +01:00
|
|
|
|
|
|
|
//only return an id if a new loadout was added
|
|
|
|
if (newLoadoutId) {
|
|
|
|
return newLoadoutId.toString();
|
|
|
|
}
|
2023-12-14 17:34:15 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "CurrentLoadOutIds": {
|
|
|
|
const loadoutIds = equipment as IOid[]; // TODO: Check for more than just an array of oids, I think i remember one instance
|
|
|
|
inventory.CurrentLoadOutIds = loadoutIds;
|
|
|
|
break;
|
|
|
|
}
|
2024-07-03 12:33:09 +02:00
|
|
|
case "EquippedGear":
|
|
|
|
case "EquippedEmotes": {
|
|
|
|
inventory[equipmentName] = equipment as string[];
|
2023-12-14 17:34:15 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-06-20 11:46:08 +02:00
|
|
|
case "UseAdultOperatorLoadout": {
|
|
|
|
inventory.UseAdultOperatorLoadout = equipment as boolean;
|
|
|
|
break;
|
|
|
|
}
|
2025-03-29 09:27:38 -07:00
|
|
|
case "WeaponSkins": {
|
|
|
|
const itemEntries = equipment as IItemEntry;
|
|
|
|
for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) {
|
2025-04-11 06:56:45 -07:00
|
|
|
if (itemId.startsWith("ca70ca70ca70ca70")) {
|
|
|
|
logger.warn(
|
|
|
|
`unlockAllSkins does not work with favoriting items because you don't actually own it`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
const inventoryItem = inventory.WeaponSkins.id(itemId);
|
|
|
|
if (!inventoryItem) {
|
|
|
|
throw new Error(`inventory item WeaponSkins not found with id ${itemId}`);
|
|
|
|
}
|
|
|
|
if ("Favorite" in itemConfigEntries) {
|
|
|
|
inventoryItem.Favorite = itemConfigEntries.Favorite;
|
|
|
|
}
|
|
|
|
if ("IsNew" in itemConfigEntries) {
|
|
|
|
inventoryItem.IsNew = itemConfigEntries.IsNew;
|
|
|
|
}
|
|
|
|
}
|
2025-03-29 09:27:38 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-12-14 17:34:15 +01:00
|
|
|
default: {
|
2025-01-27 13:18:16 +01:00
|
|
|
if (equipmentKeys.includes(equipmentName as TEquipmentKey) && equipmentName != "ValidNewLoadoutId") {
|
|
|
|
logger.debug(`general Item config saved of type ${equipmentName}`, {
|
|
|
|
config: equipment
|
|
|
|
});
|
|
|
|
|
|
|
|
const itemEntries = equipment as IItemEntry;
|
|
|
|
for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) {
|
2025-02-24 20:56:34 -08:00
|
|
|
const inventoryItem = inventory[equipmentName].id(itemId);
|
2025-01-27 13:18:16 +01:00
|
|
|
|
|
|
|
if (!inventoryItem) {
|
|
|
|
throw new Error(`inventory item ${equipmentName} not found with id ${itemId}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const [configId, config] of Object.entries(itemConfigEntries)) {
|
2025-03-27 12:27:38 -07:00
|
|
|
if (typeof config !== "boolean") {
|
|
|
|
inventoryItem.Configs[parseInt(configId)] = config;
|
|
|
|
}
|
|
|
|
}
|
2025-04-11 06:56:45 -07:00
|
|
|
if ("Favorite" in itemConfigEntries) {
|
|
|
|
inventoryItem.Favorite = itemConfigEntries.Favorite;
|
|
|
|
}
|
2025-03-27 12:27:38 -07:00
|
|
|
if ("IsNew" in itemConfigEntries) {
|
|
|
|
inventoryItem.IsNew = itemConfigEntries.IsNew;
|
2025-01-27 13:18:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
logger.warn(`loadout category not implemented, changes may be lost: ${equipmentName}`, {
|
|
|
|
config: equipment
|
|
|
|
});
|
|
|
|
}
|
2023-12-14 17:34:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await inventory.save();
|
|
|
|
};
|