返回提交历史
Modified
src/constants/timeConstants.ts
+2
-0
Added
src/controllers/api/claimCompletedRecipeController.ts
+64
-0
Modified
src/controllers/api/inventoryController.ts
+1
-0
Added
src/controllers/api/startRecipeController.ts
+21
-0
Modified
src/controllers/custom/addItemController.ts
+1
-1
Modified
src/helpers/customHelpers/addItemHelpers.ts
+6
-8
Modified
src/helpers/purchaseHelpers.ts
+1
-18
Modified
src/helpers/stringHelpers.ts
+9
-1
Modified
src/models/inventoryModels/inventoryModel.ts
+41
-30
Modified
src/routes/api.ts
+5
-0
Modified
src/services/inventoryService.ts
+1
-2
Added
src/services/itemDataService.ts
+117
-0
Modified
src/services/missionInventoryUpdateService .ts
+8
-1
Modified
src/services/purchaseService.ts
+2
-1
Added
src/services/recipeService.ts
+74
-0
Modified
src/types/inventoryTypes/inventoryTypes.ts
+10
-3
Modified
static/data/items.ts
+0
-60
XFEstudio/XFESpaceNinjaServer
Foundry 1 - Preliminary (#127)
8b50189f
代码差异
17 个文件
+363
-125
@@ -3,11 +3,13 @@ const secondsPerMinute = 60;
3
3
const minutesPerHour = 60;
4
4
const hoursPerDay = 24;
5
5
6
const unixSecond = millisecondsPerSecond;
6
7
const unixMinute = secondsPerMinute * millisecondsPerSecond;
7
8
const unixHour = unixMinute * minutesPerHour;
8
9
const unixDay = hoursPerDay * unixHour;
9
10
10
11
export const unixTimesInMs = {
12
second: unixSecond,
11
13
minute: unixMinute,
12
14
hour: unixHour,
13
15
day: unixDay
@@ -0,0 +1,64 @@
1
//this is a controller for the claimCompletedRecipe route
2
//it will claim a recipe for the user
3
4
import { Request, RequestHandler, Response } from "express";
5
import { logger } from "@/src/utils/logger";
6
import { getItemByBlueprint, getItemCategoryByUniqueName } from "@/src/services/itemDataService";
7
import { IOid } from "@/src/types/commonTypes";
8
import { getJSONfromString } from "@/src/helpers/stringHelpers";
9
import { getInventory } from "@/src/services/inventoryService";
10
import { IInventoryDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
11
12
export interface IClaimCompletedRecipeRequest {
13
RecipeIds: IOid[];
14
}
15
16
// eslint-disable-next-line @typescript-eslint/no-misused-promises
17
export const claimCompletedRecipeController: RequestHandler = async (req, res) => {
18
const claimCompletedRecipeRequest = getJSONfromString(req.body.toString()) as IClaimCompletedRecipeRequest;
19
const accountId = req.query.accountId as string;
20
if (!accountId) throw new Error("no account id");
21
22
console.log(claimCompletedRecipeRequest);
23
const inventory = await getInventory(accountId);
24
const pendingRecipe = inventory.PendingRecipes.find(
25
recipe => recipe._id?.toString() === claimCompletedRecipeRequest.RecipeIds[0].$oid
26
);
27
console.log(pendingRecipe);
28
if (!pendingRecipe) {
29
logger.error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
30
throw new Error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
31
}
32
33
//check recipe is indeed ready to be completed
34
// if (pendingRecipe.CompletionDate > new Date()) {
35
// logger.error(`recipe ${pendingRecipe._id} is not ready to be completed`);
36
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
37
// }
38
39
//get completed Items
40
const completedItemName = getItemByBlueprint(pendingRecipe.ItemType)?.uniqueName;
41
42
if (!completedItemName) {
43
logger.error(`no completed item found for recipe ${pendingRecipe._id}`);
44
throw new Error(`no completed item found for recipe ${pendingRecipe._id}`);
45
}
46
const itemCategory = getItemCategoryByUniqueName(completedItemName) as keyof typeof inventory;
47
console.log(itemCategory);
48
//TODO: remove all Schema.Mixed for inventory[itemCategory] not to be any
49
//add item
50
//inventory[itemCategory].
51
52
//add additional item components like mods or weapons for a sentinel.
53
//const additionalItemComponents = itemComponents[uniqueName]
54
//add these items to inventory
55
//return changes as InventoryChanges
56
57
//remove pending recipe
58
inventory.PendingRecipes.pull(pendingRecipe._id);
59
// await inventory.save();
60
61
logger.debug("Claiming Completed Recipe", { completedItemName });
62
63
res.json({ InventoryChanges: {} });
64
};
@@ -24,6 +24,7 @@ const inventoryController: RequestHandler = async (request: Request, response: R
24
24
return;
25
25
}
26
26
27
//TODO: make a function that converts from database representation to client
27
28
const inventoryJSON = inventory.toJSON();
28
29
29
30
const inventoryResponse = toInventoryResponse(inventoryJSON);
@@ -0,0 +1,21 @@
1
import { parseString } from "@/src/helpers/general";
2
import { getJSONfromString } from "@/src/helpers/stringHelpers";
3
import { startRecipe } from "@/src/services/recipeService";
4
import { logger } from "@/src/utils/logger";
5
import { RequestHandler } from "express";
6
7
interface IStartRecipeRequest {
8
RecipeName: string;
9
Ids: string[];
10
}
11
12
// eslint-disable-next-line @typescript-eslint/no-misused-promises
13
export const startRecipeController: RequestHandler = async (req, res) => {
14
const startRecipeRequest = getJSONfromString(req.body.toString()) as IStartRecipeRequest;
15
logger.debug("StartRecipe Request", { startRecipeRequest });
16
17
const accountId = parseString(req.query.accountId);
18
19
const newRecipeId = await startRecipe(startRecipeRequest.RecipeName, accountId);
20
res.json(newRecipeId);
21
};
@@ -1,5 +1,5 @@
1
1
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
2
import { getWeaponType } from "@/src/helpers/purchaseHelpers";
2
import { getWeaponType } from "@/src/services/itemDataService";
3
3
import { addPowerSuit, addWeapon } from "@/src/services/inventoryService";
4
4
import { RequestHandler } from "express";
5
5
@@ -1,5 +1,5 @@
1
1
import { isString, parseString } from "@/src/helpers/general";
2
import { items } from "@/static/data/items";
2
import { items } from "@/src/services/itemDataService";
3
3
4
4
export enum ItemType {
5
5
Powersuit = "Powersuit",
@@ -23,20 +23,20 @@ interface IAddItemRequest {
23
23
InternalName: string;
24
24
accountId: string;
25
25
}
26
export const isInternalName = (internalName: string): boolean => {
26
export const isInternalItemName = (internalName: string): boolean => {
27
27
const item = items.find(i => i.uniqueName === internalName);
28
28
return Boolean(item);
29
29
};
30
30
31
const parseInternalName = (internalName: unknown): string => {
32
if (!isString(internalName) || !isInternalName(internalName)) {
31
const parseInternalItemName = (internalName: unknown): string => {
32
if (!isString(internalName) || !isInternalItemName(internalName)) {
33
33
throw new Error("incorrect internal name");
34
34
}
35
35
36
36
return internalName;
37
37
};
38
38
39
const toAddItemRequest = (body: unknown): IAddItemRequest => {
39
export const toAddItemRequest = (body: unknown): IAddItemRequest => {
40
40
if (!body || typeof body !== "object") {
41
41
throw new Error("incorrect or missing add item request data");
42
42
}
@@ -44,12 +44,10 @@ const toAddItemRequest = (body: unknown): IAddItemRequest => {
44
44
if ("type" in body && "internalName" in body && "accountId" in body) {
45
45
return {
46
46
type: parseItemType(body.type),
47
InternalName: parseInternalName(body.internalName),
47
InternalName: parseInternalItemName(body.internalName),
48
48
accountId: parseString(body.accountId)
49
49
};
50
50
}
51
51
52
52
throw new Error("malformed add item request");
53
53
};
54
55
export { toAddItemRequest };
@@ -1,8 +1,7 @@
1
1
import { parseBoolean, parseNumber, parseString } from "@/src/helpers/general";
2
import { WeaponTypeInternal } from "@/src/services/inventoryService";
2
import { weapons } from "@/src/services/itemDataService";
3
3
import { slotPurchaseNameToSlotName } from "@/src/services/purchaseService";
4
4
import { IPurchaseRequest, SlotPurchaseName } from "@/src/types/purchaseTypes";
5
import { weapons } from "@/static/data/items";
6
5
7
6
export const toPurchaseRequest = (purchaseRequest: unknown): IPurchaseRequest => {
8
7
if (!purchaseRequest || typeof purchaseRequest !== "object") {
@@ -41,22 +40,6 @@ export const toPurchaseRequest = (purchaseRequest: unknown): IPurchaseRequest =>
41
40
throw new Error("invalid purchaseRequest");
42
41
};
43
42
44
export const getWeaponType = (weaponName: string) => {
45
const weaponInfo = weapons.find(i => i.uniqueName === weaponName);
46
47
if (!weaponInfo) {
48
throw new Error(`unknown weapon ${weaponName}`);
49
}
50
51
const weaponType = weaponInfo.productCategory as WeaponTypeInternal;
52
53
if (!weaponType) {
54
throw new Error(`unknown weapon category for item ${weaponName}`);
55
}
56
57
return weaponType;
58
};
59
60
43
export const isSlotPurchaseName = (slotPurchaseName: string): slotPurchaseName is SlotPurchaseName => {
61
44
return slotPurchaseName in slotPurchaseNameToSlotName;
62
45
};
@@ -1,4 +1,4 @@
1
export const getJSONfromString = (str: string): any => {
1
export const getJSONfromString = (str: string) => {
2
2
const jsonSubstring = str.substring(0, str.lastIndexOf("}") + 1);
3
3
return JSON.parse(jsonSubstring);
4
4
};
@@ -16,3 +16,11 @@ export const getSubstringFromKeywordToKeyword = (str: string, keywordBegin: stri
16
16
const endIndex = str.indexOf(keywordEnd);
17
17
return str.substring(beginIndex, endIndex + 1);
18
18
};
19
20
export const getIndexAfter = (str: string, searchWord: string) => {
21
const index = str.indexOf(searchWord);
22
if (index === -1) {
23
return -1;
24
}
25
return index + searchWord.length;
26
};
@@ -1,4 +1,4 @@
1
import { Model, Schema, Types, model } from "mongoose";
1
import { HydratedDocument, Model, Schema, Types, model } from "mongoose";
2
2
import {
3
3
IFlavourItem,
4
4
IRawUpgrade,
@@ -10,7 +10,9 @@ import {
10
10
ISlots,
11
11
IGenericItem,
12
12
IMailbox,
13
IDuviriInfo
13
IDuviriInfo,
14
IPendingRecipe as IPendingRecipeDatabase,
15
IPendingRecipeResponse
14
16
} from "../../types/inventoryTypes/inventoryTypes";
15
17
import { IMongoDate, IOid } from "../../types/commonTypes";
16
18
import { ISuitDatabase } from "@/src/types/inventoryTypes/SuitTypes";
@@ -25,6 +27,29 @@ import {
25
27
} from "@/src/types/inventoryTypes/commonInventoryTypes";
26
28
import { toOid } from "@/src/helpers/inventoryHelpers";
27
29
30
const pendingRecipeSchema = new Schema<IPendingRecipeDatabase>(
31
{
32
ItemType: String,
33
CompletionDate: Date
34
},
35
{ id: false }
36
);
37
38
pendingRecipeSchema.virtual("ItemId").get(function () {
39
return { $oid: this._id.toString() };
40
});
41
42
pendingRecipeSchema.set("toJSON", {
43
virtuals: true,
44
transform(_document, returnedObject) {
45
delete returnedObject._id;
46
delete returnedObject.__v;
47
(returnedObject as IPendingRecipeResponse).CompletionDate = {
48
$date: { $numberLong: (returnedObject as IPendingRecipeDatabase).CompletionDate.getTime().toString() }
49
};
50
}
51
});
52
28
53
const polaritySchema = new Schema<IPolarity>({
29
54
Slot: Number,
30
55
Value: String
@@ -296,7 +321,6 @@ DuviriInfoSchema.set("toJSON", {
296
321
});
297
322
298
323
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
299
300
324
accountOwnerId: Schema.Types.ObjectId,
301
325
SubscribedToEmails: Number,
302
326
Created: Schema.Types.Mixed,
@@ -325,7 +349,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
325
349
MechBin: slotsBinSchema,
326
350
CrewMemberBin: slotsBinSchema,
327
351
328
329
352
//How many trades do you have left
330
353
TradesRemaining: Number,
331
354
//How many Gift do you have left*(gift spends the trade)
@@ -351,10 +374,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
351
374
DailyAffiliationZariman: Number,
352
375
DailyAffiliationKahl: Number,
353
376
354
355
377
//Daily Focus limit
356
378
DailyFocus: Number,
357
//you not used Focus
379
//you not used Focus
358
380
FocusXP: Schema.Types.Mixed,
359
381
//Curent active like Active school focuses is = "Zenurik"
360
382
FocusAbility: String,
@@ -441,24 +463,21 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
441
463
//Railjack/Components(https://warframe.fandom.com/wiki/Railjack/Components)
442
464
CrewShipRawSalvage: [Schema.Types.Mixed],
443
465
444
445
466
//Default RailJack
446
467
CrewShips: [Schema.Types.Mixed],
447
468
CrewShipAmmo: [Schema.Types.Mixed],
448
469
CrewShipWeapons: [Schema.Types.Mixed],
449
470
CrewShipWeaponSkins: [Schema.Types.Mixed],
450
471
451
452
472
//NPC Crew and weapon
453
473
CrewMembers: [Schema.Types.Mixed],
454
474
CrewShipSalvagedWeaponSkins: [Schema.Types.Mixed],
455
475
CrewShipSalvagedWeapons: [Schema.Types.Mixed],
456
476
457
458
477
//Complete Mission\Quests
459
478
Missions: [Schema.Types.Mixed],
460
479
QuestKeys: [Schema.Types.Mixed],
461
//item like DojoKey or Boss missions key
480
//item like DojoKey or Boss missions key
462
481
LevelKeys: [Schema.Types.Mixed],
463
482
//Active quests
464
483
Quests: [Schema.Types.Mixed],
@@ -478,25 +497,22 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
478
497
//Retries rank up(3 time)
479
498
TrainingRetriesLeft: Number,
480
499
481
482
500
//you saw last played Region when you opened the star map
483
501
LastRegionPlayed: String,
484
502
485
503
//Blueprint
486
504
Recipes: [Schema.Types.Mixed],
487
505
//Crafting Blueprint(Item Name + CompletionDate)
488
PendingRecipes: [Schema.Types.Mixed],
506
PendingRecipes: [pendingRecipeSchema],
489
507
490
508
//warframe\Weapon skins
491
509
WeaponSkins: [Schema.Types.Mixed],
492
510
493
494
511
//Ayatan Item
495
512
FusionTreasures: [Schema.Types.Mixed],
496
513
//"node": "TreasureTutorial", "state": "TS_COMPLETED"
497
514
TauntHistory: [Schema.Types.Mixed],
498
515
499
500
516
//noShow2FA,VisitPrimeVault etc
501
517
WebFlags: Schema.Types.Mixed,
502
518
//Id CompletedAlerts
@@ -508,7 +524,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
508
524
//Alert->Kuva Siphon
509
525
PeriodicMissionCompletions: [Schema.Types.Mixed],
510
526
511
512
527
//Codex->LoreFragment
513
528
LoreFragmentScans: [Schema.Types.Mixed],
514
529
@@ -520,7 +535,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
520
535
ActiveDojoColorResearch: String,
521
536
522
537
SentientSpawnChanceBoosters: Schema.Types.Mixed,
523
538
524
539
QualifyingInvasions: [Schema.Types.Mixed],
525
540
FactionScores: [Number],
526
541
@@ -530,11 +545,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
530
545
//If you want change Spectre Gear id
531
546
PendingSpectreLoadouts: [Schema.Types.Mixed],
532
547
533
534
548
//New quest Email spam
535
549
//example:"ItemType": "/Lotus/Types/Keys/RailJackBuildQuest/RailjackBuildQuestEmailItem",
536
550
EmailItems: [Schema.Types.Mixed],
537
538
551
539
552
//Profile->Wishlist
540
553
Wishlist: [String],
@@ -561,7 +574,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
561
574
562
575
//Game mission\ivent score example "Tag": "WaterFight", "Best": 170, "Count": 1258,
563
576
PersonalGoalProgress: [Schema.Types.Mixed],
564
577
565
578
//Setting interface Style
566
579
ThemeStyle: String,
567
580
ThemeBackground: String,
@@ -579,7 +592,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
579
592
//Night Wave Challenge
580
593
SeasonChallengeHistory: [Schema.Types.Mixed],
581
594
582
583
595
//Cephalon Simaris Entries Example:"TargetType"+"Scans"(1-10)+"Completed": true|false
584
596
LibraryPersonalProgress: [Schema.Types.Mixed],
585
597
//Cephalon Simaris Daily Task
@@ -587,23 +599,23 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
587
599
588
600
//https://warframe.fandom.com/wiki/Invasion
589
601
InvasionChainProgress: [Schema.Types.Mixed],
590
602
591
603
//https://warframe.fandom.com/wiki/Parazon
592
604
DataKnives: [GenericItemSchema],
593
605
594
606
//CorpusLich or GrineerLich
595
607
NemesisAbandonedRewards: [String],
596
//CorpusLich\KuvaLich
608
//CorpusLich\KuvaLich
597
609
NemesisHistory: [Schema.Types.Mixed],
598
610
LastNemesisAllySpawnTime: Schema.Types.Mixed,
599
611
600
612
//TradingRulesConfirmed,ShowFriendInvNotifications(Option->Social)
601
613
Settings: Schema.Types.Mixed,
602
614
603
//Railjack craft
615
//Railjack craft
604
616
//https://warframe.fandom.com/wiki/Rising_Tide
605
617
PersonalTechProjects: [Schema.Types.Mixed],
606
618
607
619
//Modulars lvl and exp(Railjack|Duviri)
608
620
//https://warframe.fandom.com/wiki/Intrinsics
609
621
PlayerSkills: Schema.Types.Mixed,
@@ -611,7 +623,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
611
623
//TradeBannedUntil data
612
624
TradeBannedUntil: Schema.Types.Mixed,
613
625
614
615
626
//https://warframe.fandom.com/wiki/Helminth
616
627
InfestedFoundry: Schema.Types.Mixed,
617
628
NextRefill: Schema.Types.Mixed,
@@ -624,7 +635,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
624
635
//https://warframe.fandom.com/wiki/Incarnon
625
636
EvolutionProgress: [Schema.Types.Mixed],
626
637
627
628
638
//Unknown and system
629
639
DuviriInfo: DuviriInfoSchema,
630
640
Mailbox: MailboxSchema,
@@ -650,7 +660,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
650
660
CollectibleSeries: [Schema.Types.Mixed],
651
661
HasResetAccount: Boolean,
652
662
653
//Discount Coupon
663
//Discount Coupon
654
664
PendingCoupon: Schema.Types.Mixed,
655
665
//Like BossAladV,BossCaptainVor come for you on missions % chance
656
666
DeathMarks: [String],
@@ -685,13 +695,14 @@ type InventoryDocumentProps = {
685
695
MiscItems: Types.DocumentArray<IMiscItem>;
686
696
Boosters: Types.DocumentArray<IBooster>;
687
697
OperatorLoadOuts: Types.DocumentArray<IOperatorConfigClient>;
688
AdultOperatorLoadOuts: Types.DocumentArray<IOperatorConfigClient>;
698
AdultOperatorLoadOuts: Types.DocumentArray<IOperatorConfigClient>; //TODO: this should still contain _id
689
699
MechSuits: Types.DocumentArray<ISuitDatabase>;
690
700
Scoops: Types.DocumentArray<IGenericItem>;
691
701
DataKnives: Types.DocumentArray<IGenericItem>;
692
702
DrifterMelee: Types.DocumentArray<IGenericItem>;
693
703
Sentinels: Types.DocumentArray<IWeaponDatabase>;
694
704
Horses: Types.DocumentArray<IGenericItem>;
705
PendingRecipes: Types.DocumentArray<IPendingRecipeDatabase>;
695
706
};
696
707
697
708
type InventoryModelType = Model<IInventoryDatabase, {}, InventoryDocumentProps>;
@@ -35,6 +35,8 @@ import express from "express";
35
35
import { setBootLocationController } from "@/src/controllers/api/setBootLocationController";
36
36
import { focusController } from "@/src/controllers/api/focusController";
37
37
import { inventorySlotsController } from "@/src/controllers/api/inventorySlotsController";
38
import { startRecipeController } from "@/src/controllers/api/startRecipeController";
39
import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompletedRecipeController";
38
40
39
41
const apiRouter = express.Router();
40
42
@@ -62,6 +64,9 @@ apiRouter.get("/logout.php", logoutController);
62
64
apiRouter.get("/setBootLocation.php", setBootLocationController);
63
65
64
66
// post
67
// eslint-disable-next-line @typescript-eslint/no-misused-promises
68
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
69
apiRouter.post("/startRecipe.php", startRecipeController);
65
70
apiRouter.post("/inventorySlots.php", inventorySlotsController);
66
71
apiRouter.post("/focus.php", focusController);
67
72
apiRouter.post("/artifacts.php", artifactsController);
@@ -17,6 +17,7 @@ import {
17
17
import { IGenericUpdate } from "../types/genericUpdate";
18
18
import { IArtifactsRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
19
19
import { logger } from "@/src/utils/logger";
20
import { WeaponTypeInternal } from "@/src/services/itemDataService";
20
21
21
22
export const createInventory = async (accountOwnerId: Types.ObjectId, loadOutPresetId: Types.ObjectId) => {
22
23
try {
@@ -145,8 +146,6 @@ export const updateGeneric = async (data: IGenericUpdate, accountId: string) =>
145
146
return data;
146
147
};
147
148
148
export type WeaponTypeInternal = "LongGuns" | "Pistols" | "Melee";
149
150
149
export const addWeapon = async (
151
150
weaponType: WeaponTypeInternal,
152
151
weaponName: string,
@@ -0,0 +1,117 @@
1
import { getIndexAfter } from "@/src/helpers/stringHelpers";
2
import { logger } from "@/src/utils/logger";
3
import Items, { Buildable, Category, Item, Warframe, Weapon } from "warframe-items";
4
5
type MinWeapon = Omit<Weapon, "patchlogs">;
6
type MinItem = Omit<Item, "patchlogs">;
7
8
export const weapons: MinWeapon[] = (new Items({ category: ["Primary", "Secondary", "Melee"] }) as Weapon[]).map(
9
item => {
10
const next = { ...item };
11
delete next.patchlogs;
12
return next;
13
}
14
);
15
16
export type WeaponTypeInternal = "LongGuns" | "Pistols" | "Melee";
17
18
export const items: MinItem[] = new Items({ category: ["All"] }).map(item => {
19
const next = { ...item };
20
delete next.patchlogs;
21
return next;
22
});
23
24
export const getWeaponType = (weaponName: string) => {
25
const weaponInfo = weapons.find(i => i.uniqueName === weaponName);
26
27
if (!weaponInfo) {
28
throw new Error(`unknown weapon ${weaponName}`);
29
}
30
31
const weaponType = weaponInfo.productCategory as WeaponTypeInternal;
32
33
if (!weaponType) {
34
logger.error(`unknown weapon category for item ${weaponName}`);
35
throw new Error(`unknown weapon category for item ${weaponName}`);
36
}
37
38
return weaponType;
39
};
40
41
const getNamesObj = (category: Category) =>
42
new Items({ category: [category] }).reduce<{ [index: string]: string }>((acc, item) => {
43
acc[item.name!.replace("'S", "'s")] = item.uniqueName!;
44
return acc;
45
}, {});
46
47
export const modNames = getNamesObj("Mods");
48
export const resourceNames = getNamesObj("Resources");
49
export const miscNames = getNamesObj("Misc");
50
export const relicNames = getNamesObj("Relics");
51
export const skinNames = getNamesObj("Skins");
52
export const arcaneNames = getNamesObj("Arcanes");
53
export const gearNames = getNamesObj("Gear");
54
//logger.debug(`gear names`, { gearNames });
55
56
export const craftNames = Object.fromEntries(
57
(
58
new Items({
59
category: [
60
"Warframes",
61
"Gear",
62
"Melee",
63
"Primary",
64
"Secondary",
65
"Sentinels",
66
"Misc",
67
"Arch-Gun",
68
"Arch-Melee"
69
]
70
}) as Warframe[]
71
)
72
.flatMap(item => item.components || [])
73
.filter(item => item.drops && item.drops[0])
74
.map(item => [item.drops![0].type, item.uniqueName])
75
);
76
77
export const blueprintNames = Object.fromEntries(
78
Object.keys(craftNames)
79
.filter(name => name.includes("Blueprint"))
80
.map(name => [name, craftNames[name]])
81
);
82
83
const buildables = items.filter(item => !!(item as Buildable).components);
84
85
export const getItemByBlueprint = (uniqueName: string): (MinItem & Buildable) | undefined => {
86
const item = buildables.find(
87
item => (item as Buildable).components?.find(component => component.uniqueName === uniqueName)
88
);
89
return item;
90
};
91
92
export const getItemCategoryByUniqueName = (uniqueName: string) => {
93
//Lotus/Types/Items/MiscItems/PolymerBundle
94
95
let splitWord = "Items/";
96
if (!uniqueName.includes("/Items/")) {
97
splitWord = "/Types/";
98
}
99
100
const index = getIndexAfter(uniqueName, splitWord);
101
if (index === -1) {
102
logger.error(`error parsing item category ${uniqueName}`);
103
throw new Error(`error parsing item category ${uniqueName}`);
104
}
105
const category = uniqueName.substring(index).split("/")[0];
106
return category;
107
};
108
109
export const getItemByUniqueName = (uniqueName: string) => {
110
const item = items.find(item => item.uniqueName === uniqueName);
111
return item;
112
};
113
114
export const getItemByName = (name: string) => {
115
const item = items.find(item => item.name === name);
116
return item;
117
};