feat: implement feeding of helminth #597
8
package-lock.json
generated
@ -12,7 +12,7 @@
|
||||
"copyfiles": "^2.4.1",
|
||||
"express": "^5.0.0-beta.3",
|
||||
"mongoose": "^8.9.2",
|
||||
"warframe-public-export-plus": "^0.5.7",
|
||||
"warframe-public-export-plus": "^0.5.8",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
@ -3877,9 +3877,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/warframe-public-export-plus": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.7.tgz",
|
||||
"integrity": "sha512-5cT48YPZCJ/KGCtAK4hGtaE6709CYIPzCJUI/8odJxntnUfe2R3Np+T8+iw431H2mVA+4CF9ByhvicODhdBPLw=="
|
||||
"version": "0.5.8",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.8.tgz",
|
||||
"integrity": "sha512-ZhHrKIkI6nhjKDlxhrNcfN8r2Yc9g+eeKLS6+9w7gzC4NscIt6TU8tH8bfjJTDeo6nRrzt88szX1/Oo3WnUY4Q=="
|
||||
},
|
||||
"node_modules/warframe-riven-info": {
|
||||
"version": "0.1.2",
|
||||
|
@ -16,7 +16,7 @@
|
||||
"copyfiles": "^2.4.1",
|
||||
"express": "^5.0.0-beta.3",
|
||||
"mongoose": "^8.9.2",
|
||||
"warframe-public-export-plus": "^0.5.7",
|
||||
"warframe-public-export-plus": "^0.5.8",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
|
@ -3,6 +3,8 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getInventory, addMiscItems } from "@/src/services/inventoryService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { ExportMisc } from "warframe-public-export-plus";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
@ -53,6 +55,57 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case "c": {
|
||||
// consume items
|
||||
const request = getJSONfromString(String(req.body)) as IHelminthFeedRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.Resources ??= [];
|
||||
inventory.InfestedFoundry.XP ??= 0;
|
||||
|
||||
const miscItemChanges: IMiscItem[] = [];
|
||||
let totalPercentagePointsGained = 0;
|
||||
|
||||
for (const contribution of request.ResourceContributions) {
|
||||
const snack = ExportMisc.helminthSnacks[contribution.ItemType];
|
||||
|
||||
// Note: Currently ignoring loss of apetite
|
||||
totalPercentagePointsGained += snack.gain / 0.01;
|
||||
const resource = inventory.InfestedFoundry.Resources.find(x => x.ItemType == snack.type);
|
||||
if (resource) {
|
||||
resource.Count += Math.trunc(snack.gain * 1000);
|
||||
} else {
|
||||
inventory.InfestedFoundry.Resources.push({
|
||||
ItemType: snack.type,
|
||||
Count: Math.trunc(snack.gain * 1000)
|
||||
});
|
||||
}
|
||||
|
||||
// tally items for removal
|
||||
const change = miscItemChanges.find(x => x.ItemType == contribution.ItemType);
|
||||
if (change) {
|
||||
change.ItemCount -= snack.count;
|
||||
} else {
|
||||
miscItemChanges.push({ ItemType: contribution.ItemType, ItemCount: snack.count * -1 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inventory.InfestedFoundry.XP += 666 * totalPercentagePointsGained;
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
InfestedFoundry: {
|
||||
XP: inventory.InfestedFoundry.XP,
|
||||
![]() 💡 Codebase verification Verify negative item counts in inventory. Example locations that need attention:
🔗 Analysis chainVerify negative item counts. Let me check the implementation of Let me try a different pattern to find the implementation. Let me try one more search pattern to locate the implementation. 🏁 Scripts executedThe following scripts were executed for the analysis: Script:
Length of output: 16660 Script:
Length of output: 58 Script:
Length of output: 100 Script:
Length of output: 1303 _:bulb: Codebase verification_
**Verify negative item counts in inventory.**
The `addMiscItems` implementation in `inventoryService.ts` does not check for negative item counts when updating the inventory. This could lead to negative inventory states when removing items. Please add validation to ensure item counts don't go below zero.
Example locations that need attention:
- `src/services/inventoryService.ts`: Add validation in `addMiscItems` function before updating `MiscItems[itemIndex].ItemCount` to prevent negative values
- `src/controllers/api/infestedFoundryController.ts`: Add pre-validation before calling `addMiscItems` to ensure the player has enough items to remove
<details>
<summary>🔗 Analysis chain</summary>
**Verify negative item counts.**
When removing items from the player’s inventory, confirm that the user’s existing item count isn’t going below zero. This can prevent accidental negative inventory states.
---
Let me check the implementation of `addMiscItems` to verify how it handles negative item counts.
---
Let me try a different pattern to find the implementation.
---
Let me try one more search pattern to locate the implementation.
</details>
<details>
<summary>🏁 Scripts executed</summary>
The following scripts were executed for the analysis:
Script:
```shell
#!/bin/bash
# Check for any references to 'addMiscItems' calls that allow negative item counts.
rg -A 3 --json $'addMiscItems\\('
```
Length of output: 16660
---
Script:
```shell
#!/bin/bash
# Find the implementation of addMiscItems function
ast-grep --pattern 'function addMiscItems($_) {
$$$
}'
```
Length of output: 58
---
Script:
```shell
#!/bin/bash
# Find the implementation of addMiscItems function with export
ast-grep --pattern 'export function addMiscItems($_) {
$$$
}'
# Also search with ripgrep for any definition
rg -A 10 "function addMiscItems"
```
Length of output: 100
---
Script:
```shell
#!/bin/bash
# Search for the file containing addMiscItems implementation
fd -t f -e ts | xargs rg -l "addMiscItems.*="
# Then look for the actual implementation
rg -A 15 "addMiscItems.*="
```
Length of output: 1303
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
|
||||
Resources: inventory.InfestedFoundry.Resources
|
||||
}
|
||||
},
|
||||
MiscItems: miscItemChanges
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "o": // offerings update
|
||||
// {"OfferingsIndex":540,"SuitTypes":["/Lotus/Powersuits/PaxDuviricus/PaxDuviricusBaseSuit","/Lotus/Powersuits/Nezha/NezhaBaseSuit","/Lotus/Powersuits/Devourer/DevourerBaseSuit"],"Extra":false}
|
||||
res.status(404).end();
|
||||
@ -74,6 +127,13 @@ interface IHelminthNameRequest {
|
||||
newName: string;
|
||||
}
|
||||
|
||||
interface IHelminthFeedRequest {
|
||||
ResourceContributions: {
|
||||
ItemType: string;
|
||||
Date: number; // unix timestamp
|
||||
}[];
|
||||
}
|
||||
|
||||
const colorToShard: Record<string, string> = {
|
||||
ACC_RED: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalAmar",
|
||||
ACC_RED_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalAmarMythic",
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
IPlayerSkills,
|
||||
ISettings,
|
||||
IInfestedFoundry,
|
||||
IHelminthResource,
|
||||
IConsumedSuit,
|
||||
IQuestProgress,
|
||||
IQuestKeyDatabase,
|
||||
@ -454,10 +455,12 @@ const consumedSchuitsSchema = new Schema<IConsumedSuit>({
|
||||
c: colorSchema
|
||||
});
|
||||
|
||||
const helminthResourceSchema = new Schema<IHelminthResource>({ ItemType: String, Count: Number }, { _id: false });
|
||||
|
||||
const infestedFoundrySchema = new Schema<IInfestedFoundry>(
|
||||
{
|
||||
Name: String,
|
||||
Resources: { type: [typeCountSchema], default: undefined },
|
||||
Resources: { type: [helminthResourceSchema], default: undefined },
|
||||
Slots: Number,
|
||||
XP: Number,
|
||||
ConsumedSuits: { type: [consumedSchuitsSchema], default: undefined },
|
||||
![]() 🛠️ Refactor suggestion Schema definition is correct; consider adding validations.
📝 Committable suggestion
_:hammer_and_wrench: Refactor suggestion_
**Schema definition is correct; consider adding validations.**
You might add a minimum value validator for “Count” to avoid impossible negative states.
```diff
- const helminthResourceSchema = new Schema<IHelminthResource>({ ItemType: String, Count: Number }, { _id: false });
+ const helminthResourceSchema = new Schema<IHelminthResource>({
+ ItemType: { type: String, required: true },
+ Count: { type: Number, required: true, min: 0 }
+ }, { _id: false });
```
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
`````suggestion
const helminthResourceSchema = new Schema<IHelminthResource>({
ItemType: { type: String, required: true },
Count: { type: Number, required: true, min: 0 }
}, { _id: false });
`````
</details>
<!-- suggestion_end -->
<!-- This is an auto-generated comment by CodeRabbit -->
|
||||
|
@ -524,9 +524,15 @@ export interface IFusionTreasure {
|
||||
Sockets: number;
|
||||
}
|
||||
|
||||
// Like ITypeCount except 'Count' instead of 'ItemCount'
|
||||
export interface IHelminthResource {
|
||||
ItemType: string;
|
||||
Count: number;
|
||||
}
|
||||
|
||||
export interface IInfestedFoundry {
|
||||
Name?: string;
|
||||
Resources?: ITypeCount[];
|
||||
Resources?: IHelminthResource[];
|
||||
Slots?: number;
|
||||
XP?: number;
|
||||
ConsumedSuits?: IConsumedSuit[];
|
||||
|
⚠️ Potential issue
Handle potential missing snack data.
If a contribution’s “ItemType” is not present in “ExportMisc.helminthSnacks”, “snack” would be undefined, causing a runtime error. Consider adding a guard clause to handle missing or invalid keys.
Proposed check: