clear types & getRotations fix

This commit is contained in:
holmityd 2023-09-07 14:03:02 +04:00
parent 01cfecd9d2
commit bc9cf70092
10 changed files with 128 additions and 166 deletions

View File

@ -1,19 +1,18 @@
import { parseString } from "@/src/helpers/general";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { upgradeMod } from "@/src/services/inventoryService"; import { upgradeMod } from "@/src/services/inventoryService";
import { IArtifactsRequest } from "@/src/types/requestTypes";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
// eslint-disable-next-line @typescript-eslint/no-misused-promises // eslint-disable-next-line @typescript-eslint/no-misused-promises
const artifactsController: RequestHandler = async (req, res) => { const artifactsController: RequestHandler = async (req, res) => {
const [data] = String(req.body).split("\n"); const accountId = parseString(req.query.accountId);
const id = req.query.accountId as string;
// TODO - salt check
try { try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
const parsedData = JSON.parse(data); const artifactsData = getJSONfromString(req.body.toString()) as IArtifactsRequest;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const upgradeModId = await upgradeMod(parsedData, id); const upgradeModId = await upgradeMod(artifactsData, accountId);
res.send(upgradeModId); res.send(upgradeModId);
} catch (err) { } catch (err) {
console.error("Error parsing JSON data:", err); console.error("Error parsing JSON data:", err);

View File

@ -1,7 +1,9 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { missionInventoryUpdate } from "@/src/services/inventoryService"; import { missionInventoryUpdate } from "@/src/services/inventoryService";
import { combineRewardAndLootInventory, getRewards } from "@/src/services/missionInventoryUpdateService "; import { combineRewardAndLootInventory, getRewards } from "@/src/services/missionInventoryUpdateService ";
import { IMissionInventoryUpdate } from "@/src/types/missionInventoryUpdateType"; import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { parseString } from "@/src/helpers/general";
import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes";
/* /*
**** INPUT **** **** INPUT ****
- [ ] crossPlaySetting - [ ] crossPlaySetting
@ -43,23 +45,20 @@ import { IMissionInventoryUpdate } from "@/src/types/missionInventoryUpdateType"
*/ */
// eslint-disable-next-line @typescript-eslint/no-misused-promises // eslint-disable-next-line @typescript-eslint/no-misused-promises
const missionInventoryUpdateController: RequestHandler = async (req, res) => { const missionInventoryUpdateController: RequestHandler = async (req, res): Promise<void> => {
const [data] = String(req.body).split("\n"); const accountId = parseString(req.query.accountId);
const id = req.query.accountId as string;
try { try {
const lootInventory = JSON.parse(data) as IMissionInventoryUpdate; // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
if (typeof lootInventory !== "object" || lootInventory === null) { const lootInventory = getJSONfromString(req.body.toString()) as IMissionInventoryUpdateRequest;
throw new Error("Invalid data format");
}
const { InventoryChanges, MissionRewards } = getRewards(lootInventory.RewardInfo); const { InventoryChanges, MissionRewards } = getRewards(lootInventory);
const { combinedInventoryChanges, TotalCredits, CreditsBonus, MissionCredits, FusionPoints } = const { combinedInventoryChanges, TotalCredits, CreditsBonus, MissionCredits, FusionPoints } =
combineRewardAndLootInventory(InventoryChanges, lootInventory); combineRewardAndLootInventory(InventoryChanges, lootInventory);
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const InventoryJson = JSON.stringify(await missionInventoryUpdate(combinedInventoryChanges, id)); const InventoryJson = JSON.stringify(await missionInventoryUpdate(combinedInventoryChanges, accountId));
res.json({ res.json({
// InventoryJson, // this part will reset game data and missions will be locked // InventoryJson, // this part will reset game data and missions will be locked
MissionRewards, MissionRewards,

View File

@ -1,4 +1,4 @@
const getJSONfromString = (str: string): any => { export const getJSONfromString = (str: string): any => {
const jsonSubstring = str.substring(0, str.lastIndexOf("}") + 1); const jsonSubstring = str.substring(0, str.lastIndexOf("}") + 1);
return JSON.parse(jsonSubstring); return JSON.parse(jsonSubstring);
}; };

View File

@ -2,20 +2,19 @@ import { Inventory } from "@/src/models/inventoryModel";
import new_inventory from "@/static/fixed_responses/postTutorialInventory.json"; import new_inventory from "@/static/fixed_responses/postTutorialInventory.json";
import config from "@/config.json"; import config from "@/config.json";
import { Types } from "mongoose"; import { Types } from "mongoose";
import { ISuitResponse } from "@/src/types/inventoryTypes/SuitTypes"; import { ISuitDatabase, ISuitResponse } from "@/src/types/inventoryTypes/SuitTypes";
import { SlotType } from "@/src/types/purchaseTypes"; import { SlotType } from "@/src/types/purchaseTypes";
import { IWeaponResponse } from "@/src/types/inventoryTypes/weaponTypes"; import { IWeaponDatabase, IWeaponResponse } from "@/src/types/inventoryTypes/weaponTypes";
import { import {
IChallengeProgress, IChallengeProgress,
IConsumable, IConsumable,
ICrewShipSalvagedWeaponSkin,
IFlavourItem, IFlavourItem,
IInventoryDatabaseDocument, IInventoryDatabaseDocument,
IMiscItem, IMiscItem,
IRawUpgrade IRawUpgrade
} from "@/src/types/inventoryTypes/inventoryTypes"; } from "@/src/types/inventoryTypes/inventoryTypes";
import { IMissionInventoryUpdate, IMissionInventoryUpdateGear } from "../types/missionInventoryUpdateType";
import { IGenericUpdate } from "../types/genericUpdate"; import { IGenericUpdate } from "../types/genericUpdate";
import { IArtifactsRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
const createInventory = async (accountOwnerId: Types.ObjectId) => { const createInventory = async (accountOwnerId: Types.ObjectId) => {
try { try {
@ -139,17 +138,17 @@ export const addCustomization = async (customizatonName: string, accountId: stri
const addGearExpByCategory = ( const addGearExpByCategory = (
inventory: IInventoryDatabaseDocument, inventory: IInventoryDatabaseDocument,
gearArray: IMissionInventoryUpdateGear[] | undefined, gearArray: ISuitDatabase[] | IWeaponDatabase[] | undefined,
categoryName: "Pistols" | "LongGuns" | "Melee" | "Suits" categoryName: "Pistols" | "LongGuns" | "Melee" | "Suits"
) => { ) => {
const category = inventory[categoryName]; const category = inventory[categoryName];
gearArray?.forEach(({ ItemId, XP }) => { gearArray?.forEach(({ ItemId, XP }) => {
const itemIndex = category.findIndex(item => item._id?.equals(ItemId.$oid)); const itemIndex = ItemId ? category.findIndex(item => item._id?.equals(ItemId.$oid)) : -1;
const item = category[itemIndex]; const item = category[itemIndex];
if (itemIndex !== -1 && item.XP != undefined) { if (itemIndex !== -1 && item.XP != undefined) {
item.XP += XP; item.XP += XP || 0;
inventory.markModified(`${categoryName}.${itemIndex}.XP`); inventory.markModified(`${categoryName}.${itemIndex}.XP`);
} }
}); });
@ -232,7 +231,7 @@ const addChallenges = (inventory: IInventoryDatabaseDocument, itemsArray: IChall
const gearKeys = ["Suits", "Pistols", "LongGuns", "Melee"] as const; const gearKeys = ["Suits", "Pistols", "LongGuns", "Melee"] as const;
type GearKeysType = (typeof gearKeys)[number]; type GearKeysType = (typeof gearKeys)[number];
export const missionInventoryUpdate = async (data: IMissionInventoryUpdate, accountId: string) => { export const missionInventoryUpdate = async (data: IMissionInventoryUpdateRequest, accountId: string) => {
const { RawUpgrades, MiscItems, RegularCredits, ChallengeProgress, FusionPoints, Consumables, Recipes } = data; const { RawUpgrades, MiscItems, RegularCredits, ChallengeProgress, FusionPoints, Consumables, Recipes } = data;
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
@ -275,15 +274,8 @@ export const addBooster = async (ItemType: string, time: number, accountId: stri
await inventory.save(); await inventory.save();
}; };
export const upgradeMod = async ( export const upgradeMod = async (artifactsData: IArtifactsRequest, accountId: string): Promise<string | undefined> => {
{ const { Upgrade, LevelDiff, Cost, FusionPointCost } = artifactsData;
Upgrade,
LevelDiff,
Cost,
FusionPointCost
}: { Upgrade: ICrewShipSalvagedWeaponSkin; LevelDiff: number; Cost: number; FusionPointCost: number },
accountId: string
): Promise<string | undefined> => {
try { try {
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
const { Upgrades, RawUpgrades } = inventory; const { Upgrades, RawUpgrades } = inventory;

View File

@ -1,29 +1,26 @@
import { import { IMissionRewardResponse, IReward, IInventoryFieldType, inventoryFields } from "@/src/types/missionTypes";
IMissionInventoryUpdate,
IMissionInventoryUpdateRewardInfo,
IMissionRewardResponse,
IReward,
IInventoryFieldType,
inventoryFields
} from "@/src/types/missionInventoryUpdateType";
import missionsDropTable from "@/static/json/missions-drop-table.json"; import missionsDropTable from "@/static/json/missions-drop-table.json";
import { modNames, relicNames, miscNames, resourceNames, gearNames, blueprintNames } from "@/static/data/items"; import { modNames, relicNames, miscNames, resourceNames, gearNames, blueprintNames } from "@/static/data/items";
import { IMissionInventoryUpdateRequest } from "../types/requestTypes";
// need reverse engineer rewardSeed, otherwise ingame displayed rotation reward will be different than added to db or displayed on mission end // need reverse engineer rewardSeed, otherwise ingame displayed rotation reward will be different than added to db or displayed on mission end
const getRewards = ( const getRewards = ({
rewardInfo: IMissionInventoryUpdateRewardInfo | undefined RewardInfo
): { InventoryChanges: IMissionInventoryUpdate; MissionRewards: IMissionRewardResponse[] } => { }: IMissionInventoryUpdateRequest): {
if (!rewardInfo) { InventoryChanges: IMissionInventoryUpdateRequest;
MissionRewards: IMissionRewardResponse[];
} => {
if (!RewardInfo) {
return { InventoryChanges: {}, MissionRewards: [] }; return { InventoryChanges: {}, MissionRewards: [] };
} }
const rewards = (missionsDropTable as { [key: string]: IReward[] })[rewardInfo.node]; const rewards = (missionsDropTable as { [key: string]: IReward[] })[RewardInfo.node];
if (!rewards) { if (!rewards) {
return { InventoryChanges: {}, MissionRewards: [] }; return { InventoryChanges: {}, MissionRewards: [] };
} }
const rotationCount = rewardInfo.rewardQualifications?.length || 0; const rotationCount = RewardInfo.rewardQualifications?.length || 0;
const rotations = getRotations(rotationCount); const rotations = getRotations(rotationCount);
const drops: IReward[] = []; const drops: IReward[] = [];
for (const rotation of rotations) { for (const rotation of rotations) {
@ -48,26 +45,27 @@ const getRewards = (
drops.push(...guaranteedDrops); drops.push(...guaranteedDrops);
} }
// const testDrops = [ const testDrops = [
// { chance: 7.69, name: "Lith W3 Relic", rotation: "B" }, { chance: 7.69, name: "Lith W3 Relic", rotation: "B" },
// { chance: 7.69, name: "Lith W3 Relic", rotation: "B" }, { chance: 7.69, name: "Lith W3 Relic", rotation: "B" },
// { chance: 10.82, name: "2X Orokin Cell", rotation: "C" }, { chance: 10.82, name: "2X Orokin Cell", rotation: "C" },
// { chance: 10.82, name: "Arrow Mutation", rotation: "C" }, { chance: 10.82, name: "Arrow Mutation", rotation: "C" },
// { chance: 10.82, name: "200 Endo", rotation: "C" }, { chance: 10.82, name: "200 Endo", rotation: "C" },
// { chance: 10.82, name: "2,000,000 Credits Cache", rotation: "C" }, { chance: 10.82, name: "200 Endo", rotation: "C" },
// { chance: 7.69, name: "Health Restore (Large)", rotation: "C" }, { chance: 10.82, name: "2,000,000 Credits Cache", rotation: "C" },
// { chance: 7.69, name: "Vapor Specter Blueprint", rotation: "C" } { chance: 7.69, name: "Health Restore (Large)", rotation: "C" },
// ]; { chance: 7.69, name: "Vapor Specter Blueprint", rotation: "C" }
// console.log("Mission rewards:", testDrops); ];
// return formatRewardsToInventoryType(testDrops); console.log("Mission rewards:", testDrops);
return formatRewardsToInventoryType(testDrops);
console.log("Mission rewards:", drops); console.log("Mission rewards:", drops);
return formatRewardsToInventoryType(drops); return formatRewardsToInventoryType(drops);
}; };
const combineRewardAndLootInventory = ( const combineRewardAndLootInventory = (
rewardInventory: IMissionInventoryUpdate, rewardInventory: IMissionInventoryUpdateRequest,
lootInventory: IMissionInventoryUpdate lootInventory: IMissionInventoryUpdateRequest
) => { ) => {
const missionCredits = lootInventory.RegularCredits || 0; const missionCredits = lootInventory.RegularCredits || 0;
const creditsBonus = rewardInventory.RegularCredits || 0; const creditsBonus = rewardInventory.RegularCredits || 0;
@ -98,12 +96,10 @@ const getRotations = (rotationCount: number): (string | undefined)[] => {
if (rotationCount === 0) return [undefined]; if (rotationCount === 0) return [undefined];
const rotationPattern = ["A", "A", "B", "C"]; const rotationPattern = ["A", "A", "B", "C"];
let rotationIndex = 0;
const rotatedValues = []; const rotatedValues = [];
for (let i = 1; i <= rotationCount; i++) { for (let i = 0; i < rotationCount; i++) {
rotatedValues.push(rotationPattern[rotationIndex]); rotatedValues.push(rotationPattern[i % rotationPattern.length]);
rotationIndex = (rotationIndex + 1) % 3;
} }
return rotatedValues; return rotatedValues;
@ -128,8 +124,8 @@ const getRandomRewardByChance = (data: IReward[] | undefined): IReward | undefin
const formatRewardsToInventoryType = ( const formatRewardsToInventoryType = (
rewards: IReward[] rewards: IReward[]
): { InventoryChanges: IMissionInventoryUpdate; MissionRewards: IMissionRewardResponse[] } => { ): { InventoryChanges: IMissionInventoryUpdateRequest; MissionRewards: IMissionRewardResponse[] } => {
const InventoryChanges: IMissionInventoryUpdate = {}; const InventoryChanges: IMissionInventoryUpdateRequest = {};
const MissionRewards: IMissionRewardResponse[] = []; const MissionRewards: IMissionRewardResponse[] = [];
for (const reward of rewards) { for (const reward of rewards) {
if (itemCheck(InventoryChanges, MissionRewards, reward.name)) { if (itemCheck(InventoryChanges, MissionRewards, reward.name)) {
@ -152,7 +148,7 @@ const formatRewardsToInventoryType = (
}; };
const itemCheck = ( const itemCheck = (
InventoryChanges: IMissionInventoryUpdate, InventoryChanges: IMissionInventoryUpdateRequest,
MissionRewards: IMissionRewardResponse[], MissionRewards: IMissionRewardResponse[],
name: string name: string
) => { ) => {
@ -184,7 +180,7 @@ const getCountFromName = (name: string) => {
}; };
const addRewardResponse = ( const addRewardResponse = (
InventoryChanges: IMissionInventoryUpdate, InventoryChanges: IMissionInventoryUpdateRequest,
MissionRewards: IMissionRewardResponse[], MissionRewards: IMissionRewardResponse[],
ItemName: string, ItemName: string,
ItemType: string, ItemType: string,

View File

@ -24,6 +24,7 @@ export interface ISuitDatabase {
FocusLens?: string; FocusLens?: string;
UnlockLevel?: number; UnlockLevel?: number;
_id: Types.ObjectId; _id: Types.ObjectId;
ItemId?: IOid;
} }
export interface SuitConfig { export interface SuitConfig {

View File

@ -22,6 +22,7 @@ export interface IWeaponDatabase {
ModularParts?: string[]; ModularParts?: string[];
UnlockLevel?: number; UnlockLevel?: number;
_id?: Types.ObjectId; _id?: Types.ObjectId;
ItemId?: IOid;
} }
export interface WeaponConfig { export interface WeaponConfig {

View File

@ -1,94 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { IOid } from "./commonTypes";
import { IDate } from "./inventoryTypes/inventoryTypes";
export const inventoryFields = ["RawUpgrades", "MiscItems", "Consumables", "Recipes"] as const;
export type IInventoryFieldType = (typeof inventoryFields)[number];
export interface IMissionInventoryUpdateGear {
ItemType: string;
ItemName: string;
ItemId: IOid;
XP: number;
UpgradeVer: number;
Features: number;
Polarized: number;
CustomizationSlotPurchases: number;
ModSlotPurchases: number;
FocusLens: string;
Expiry: IDate;
Polarity: any[];
Configs: any[];
ModularParts: any[];
SkillTree: string;
UpgradeType: string;
UpgradeFingerprint: string;
OffensiveUpgrade: string;
DefensiveUpgrade: string;
UpgradesExpiry: IDate;
ArchonCrystalUpgrades: any[];
}
export interface IMissionInventoryUpdateItem {
ItemCount: number;
ItemType: string;
}
export interface IMissionInventoryUpdateCard extends IMissionInventoryUpdateItem {
ItemId: IOid;
UpgradeFingerprint: string;
PendingRerollFingerprint: string;
LastAdded: IOid;
}
export interface IMissionInventoryUpdateChallange {
Name: string;
Progress: number;
Completed: any[];
}
export interface IMissionInventoryUpdateRewardInfo {
node: string;
rewardTier?: number;
nightmareMode?: boolean;
useVaultManifest?: boolean;
EnemyCachesFound?: number;
toxinOk?: boolean;
lostTargetWave?: number;
defenseTargetCount?: number;
EOM_AFK?: number;
rewardQualifications?: string;
PurgatoryRewardQualifications?: string;
rewardSeed?: number;
}
export interface IMissionInventoryUpdate {
rewardsMultiplier?: number;
ActiveBoosters?: any[];
LongGuns?: IMissionInventoryUpdateGear[];
Pistols?: IMissionInventoryUpdateGear[];
Suits?: IMissionInventoryUpdateGear[];
Melee?: IMissionInventoryUpdateGear[];
RawUpgrades?: IMissionInventoryUpdateItem[];
MiscItems?: IMissionInventoryUpdateItem[];
Consumables?: IMissionInventoryUpdateItem[];
Recipes?: IMissionInventoryUpdateItem[];
RegularCredits?: number;
ChallengeProgress?: IMissionInventoryUpdateChallange[];
RewardInfo?: IMissionInventoryUpdateRewardInfo;
FusionPoints?: number;
}
export interface IMissionRewardResponse {
StoreItem?: string;
TypeName: string;
UpgradeLevel?: number;
ItemCount: number;
TweetText: string;
ProductCategory: string;
}
export interface IReward {
name: string;
chance: number;
rotation?: string;
}

17
src/types/missionTypes.ts Normal file
View File

@ -0,0 +1,17 @@
export const inventoryFields = ["RawUpgrades", "MiscItems", "Consumables", "Recipes"] as const;
export type IInventoryFieldType = (typeof inventoryFields)[number];
export interface IMissionRewardResponse {
StoreItem?: string;
TypeName: string;
UpgradeLevel?: number;
ItemCount: number;
TweetText: string;
ProductCategory: string;
}
export interface IReward {
name: string;
chance: number;
rotation?: string;
}

51
src/types/requestTypes.ts Normal file
View File

@ -0,0 +1,51 @@
import {
IBooster,
IChallengeProgress,
IConsumable,
ICrewShipSalvagedWeaponSkin,
IMiscItem,
IRawUpgrade
} from "./inventoryTypes/inventoryTypes";
import { IWeaponDatabase } from "./inventoryTypes/weaponTypes";
import { ISuitDatabase } from "./inventoryTypes/SuitTypes";
interface IArtifactsRequest {
Upgrade: ICrewShipSalvagedWeaponSkin;
LevelDiff: number;
Cost: number;
FusionPointCost: number;
}
interface IMissionInventoryUpdateRequest {
rewardsMultiplier?: number;
ActiveBoosters?: IBooster[];
LongGuns?: IWeaponDatabase[];
Pistols?: IWeaponDatabase[];
Suits?: ISuitDatabase[];
Melee?: IWeaponDatabase[];
RawUpgrades?: IRawUpgrade[];
MiscItems?: IMiscItem[];
Consumables?: IConsumable[];
Recipes?: IConsumable[];
RegularCredits?: number;
ChallengeProgress?: IChallengeProgress[];
RewardInfo?: IMissionInventoryUpdateRequestRewardInfo;
FusionPoints?: number;
}
interface IMissionInventoryUpdateRequestRewardInfo {
node: string;
rewardTier?: number;
nightmareMode?: boolean;
useVaultManifest?: boolean;
EnemyCachesFound?: number;
toxinOk?: boolean;
lostTargetWave?: number;
defenseTargetCount?: number;
EOM_AFK?: number;
rewardQualifications?: string;
PurgatoryRewardQualifications?: string;
rewardSeed?: number;
}
export { IArtifactsRequest, IMissionInventoryUpdateRequest };