返回提交历史
Added
src/controllers/api/crewShipIdentifySalvageController.ts
+41
-0
Modified
src/controllers/api/guildTechController.ts
+83
-31
Modified
src/models/inventoryModels/inventoryModel.ts
+5
-0
Modified
src/routes/api.ts
+2
-0
Modified
src/services/inventoryService.ts
+21
-3
Modified
src/types/inventoryTypes/inventoryTypes.ts
+5
-3
Modified
src/types/purchaseTypes.ts
+1
-0
XFEstudio/SpaceNinjaServer
feat: identify & repair railjack components (#1664)
Closes #911 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1664 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
0ea67ea8
代码差异
7 个文件
+158
-37
@@ -0,0 +1,41 @@
1
import { addCrewShipSalvagedWeaponSkin, addCrewShipRawSalvage, getInventory } from "@/src/services/inventoryService";
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import { RequestHandler } from "express";
4
import { IInnateDamageFingerprint } from "@/src/types/inventoryTypes/inventoryTypes";
5
import { ExportCustoms } from "warframe-public-export-plus";
6
import { IFingerprintStat } from "@/src/helpers/rivenHelper";
7
import { getJSONfromString } from "@/src/helpers/stringHelpers";
8
import { IInventoryChanges } from "@/src/types/purchaseTypes";
9
10
export const crewShipIdentifySalvageController: RequestHandler = async (req, res) => {
11
const accountId = await getAccountIdForRequest(req);
12
const inventory = await getInventory(accountId, "CrewShipSalvagedWeaponSkins CrewShipRawSalvage");
13
const payload = getJSONfromString<ICrewShipIdentifySalvageRequest>(String(req.body));
14
15
const buffs: IFingerprintStat[] = [];
16
for (const upgrade of ExportCustoms[payload.ItemType].randomisedUpgrades!) {
17
buffs.push({ Tag: upgrade.tag, Value: Math.trunc(Math.random() * 0x40000000) });
18
}
19
const inventoryChanges: IInventoryChanges = addCrewShipSalvagedWeaponSkin(
20
inventory,
21
payload.ItemType,
22
JSON.stringify({ compat: payload.ItemType, buffs } satisfies IInnateDamageFingerprint)
23
);
24
25
inventoryChanges.CrewShipRawSalvage = [
26
{
27
ItemType: payload.ItemType,
28
ItemCount: -1
29
}
30
];
31
addCrewShipRawSalvage(inventory, inventoryChanges.CrewShipRawSalvage);
32
33
await inventory.save();
34
res.json({
35
InventoryChanges: inventoryChanges
36
});
37
};
38
39
interface ICrewShipIdentifySalvageRequest {
40
ItemType: string;
41
}
@@ -14,20 +14,23 @@ import {
14
14
import { ExportDojoRecipes } from "warframe-public-export-plus";
15
15
import { getAccountIdForRequest } from "@/src/services/loginService";
16
16
import {
17
addCrewShipWeaponSkin,
17
18
addItem,
18
19
addMiscItems,
19
20
addRecipes,
20
21
combineInventoryChanges,
21
22
getInventory,
23
occupySlot,
22
24
updateCurrency
23
25
} from "@/src/services/inventoryService";
24
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
26
import { IMiscItem, InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
25
27
import { IInventoryChanges } from "@/src/types/purchaseTypes";
26
28
import { config } from "@/src/services/configService";
27
29
import { GuildPermission, ITechProjectClient } from "@/src/types/guildTypes";
28
30
import { GuildMember } from "@/src/models/guildModel";
29
31
import { toMongoDate } from "@/src/helpers/inventoryHelpers";
30
32
import { logger } from "@/src/utils/logger";
33
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
31
34
32
35
export const guildTechController: RequestHandler = async (req, res) => {
33
36
const accountId = await getAccountIdForRequest(req);
@@ -99,6 +102,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
99
102
State: 0,
100
103
ReqCredits: recipe.price,
101
104
ItemType: data.RecipeType,
105
ProductCategory: data.TechProductCategory,
106
CategoryItemId: data.CategoryItemId,
102
107
ReqItems: recipe.ingredients
103
108
}) - 1
104
109
];
@@ -222,33 +227,44 @@ export const guildTechController: RequestHandler = async (req, res) => {
222
227
});
223
228
}
224
229
} else if (data.Action.split(",")[0] == "Buy") {
225
const guild = await getGuildForRequestEx(req, inventory);
226
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
227
res.status(400).send("-1").end();
228
return;
229
}
230
230
const purchase = data as IGuildTechBuyRequest;
231
const quantity = parseInt(data.Action.split(",")[1]);
232
const recipeChanges = [
233
{
234
ItemType: purchase.RecipeType,
235
ItemCount: quantity
236
}
237
];
238
addRecipes(inventory, recipeChanges);
239
const currencyChanges = updateCurrency(
240
inventory,
241
ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
242
false
243
);
244
await inventory.save();
245
// Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
246
res.json({
247
inventoryChanges: {
248
...currencyChanges,
249
Recipes: recipeChanges
231
if (purchase.Mode == "Guild") {
232
const guild = await getGuildForRequestEx(req, inventory);
233
if (
234
!hasAccessToDojo(inventory) ||
235
!(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))
236
) {
237
res.status(400).send("-1").end();
238
return;
250
239
}
251
});
240
const quantity = parseInt(data.Action.split(",")[1]);
241
const recipeChanges = [
242
{
243
ItemType: purchase.RecipeType,
244
ItemCount: quantity
245
}
246
];
247
addRecipes(inventory, recipeChanges);
248
const currencyChanges = updateCurrency(
249
inventory,
250
ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
251
false
252
);
253
await inventory.save();
254
// Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
255
res.json({
256
inventoryChanges: {
257
...currencyChanges,
258
Recipes: recipeChanges
259
}
260
});
261
} else {
262
const inventoryChanges = claimSalvagedComponent(inventory, purchase.CategoryItemId!);
263
await inventory.save();
264
res.json({
265
inventoryChanges: inventoryChanges
266
});
267
}
252
268
} else if (data.Action == "Fabricate") {
253
269
const guild = await getGuildForRequestEx(req, inventory);
254
270
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
@@ -289,9 +305,18 @@ export const guildTechController: RequestHandler = async (req, res) => {
289
305
guild.ActiveDojoColorResearch = data.RecipeType;
290
306
await guild.save();
291
307
res.end();
308
} else if (data.Action == "Rush" && data.CategoryItemId) {
309
const inventoryChanges: IInventoryChanges = {
310
...updateCurrency(inventory, 20, true),
311
...claimSalvagedComponent(inventory, data.CategoryItemId)
312
};
313
await inventory.save();
314
res.json({
315
inventoryChanges: inventoryChanges
316
});
292
317
} else {
293
318
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
294
throw new Error(`unknown guildTech action: ${data.Action}`);
319
throw new Error(`unhandled guildTech request`);
295
320
}
296
321
};
297
322
@@ -301,15 +326,15 @@ type TGuildTechRequest =
301
326
| IGuildTechContributeRequest;
302
327
303
328
interface IGuildTechBasicRequest {
304
Action: "Start" | "Fabricate" | "Pause" | "Unpause";
329
Action: "Start" | "Fabricate" | "Pause" | "Unpause" | "Cancel" | "Rush";
305
330
Mode: "Guild" | "Personal";
306
331
RecipeType: string;
332
TechProductCategory?: string;
333
CategoryItemId?: string;
307
334
}
308
335
309
interface IGuildTechBuyRequest {
336
interface IGuildTechBuyRequest extends Omit<IGuildTechBasicRequest, "Action"> {
310
337
Action: string;
311
Mode: "Guild";
312
RecipeType: string;
313
338
}
314
339
315
340
interface IGuildTechContributeRequest {
@@ -321,3 +346,30 @@ interface IGuildTechContributeRequest {
321
346
VaultCredits: number;
322
347
VaultMiscItems: IMiscItem[];
323
348
}
349
350
const claimSalvagedComponent = (inventory: TInventoryDatabaseDocument, itemId: string): IInventoryChanges => {
351
// delete personal tech project
352
const personalTechProjectIndex = inventory.PersonalTechProjects.findIndex(x => x.CategoryItemId?.equals(itemId));
353
if (personalTechProjectIndex != -1) {
354
inventory.PersonalTechProjects.splice(personalTechProjectIndex, 1);
355
}
356
357
// find salved part & delete it
358
const crewShipSalvagedWeaponSkinsIndex = inventory.CrewShipSalvagedWeaponSkins.findIndex(x => x._id.equals(itemId));
359
const crewShipWeaponSkin = inventory.CrewShipSalvagedWeaponSkins[crewShipSalvagedWeaponSkinsIndex];
360
inventory.CrewShipSalvagedWeaponSkins.splice(crewShipSalvagedWeaponSkinsIndex, 1);
361
362
// add final item
363
const inventoryChanges = {
364
...addCrewShipWeaponSkin(inventory, crewShipWeaponSkin.ItemType, crewShipWeaponSkin.UpgradeFingerprint),
365
...occupySlot(inventory, InventorySlot.RJ_COMPONENT_AND_ARMAMENTS, false)
366
};
367
368
inventoryChanges.RemovedIdItems = [
369
{
370
ItemId: { $oid: itemId }
371
}
372
];
373
374
return inventoryChanges;
375
};
@@ -504,6 +504,8 @@ const personalTechProjectSchema = new Schema<IPersonalTechProjectDatabase>({
504
504
State: Number,
505
505
ReqCredits: Number,
506
506
ItemType: String,
507
ProductCategory: String,
508
CategoryItemId: Schema.Types.ObjectId,
507
509
ReqItems: { type: [typeCountSchema], default: undefined },
508
510
HasContributions: Boolean,
509
511
CompletionDate: Date
@@ -522,6 +524,9 @@ personalTechProjectSchema.set("toJSON", {
522
524
const db = ret as IPersonalTechProjectDatabase;
523
525
const client = ret as IPersonalTechProjectClient;
524
526
527
if (db.CategoryItemId) {
528
client.CategoryItemId = toOid(db.CategoryItemId);
529
}
525
530
if (db.CompletionDate) {
526
531
client.CompletionDate = toMongoDate(db.CompletionDate);
527
532
}
@@ -27,6 +27,7 @@ import { contributeToVaultController } from "@/src/controllers/api/contributeToV
27
27
import { createAllianceController } from "@/src/controllers/api/createAllianceController";
28
28
import { createGuildController } from "@/src/controllers/api/createGuildController";
29
29
import { creditsController } from "@/src/controllers/api/creditsController";
30
import { crewShipIdentifySalvageController } from "@/src/controllers/api/crewShipIdentifySalvageController";
30
31
import { customizeGuildRanksController } from "@/src/controllers/api/customizeGuildRanksController";
31
32
import { customObstacleCourseLeaderboardController } from "@/src/controllers/api/customObstacleCourseLeaderboardController";
32
33
import { declineAllianceInviteController } from "@/src/controllers/api/declineAllianceInviteController";
@@ -218,6 +219,7 @@ apiRouter.post("/contributeToDojoComponent.php", contributeToDojoComponentContro
218
219
apiRouter.post("/contributeToVault.php", contributeToVaultController);
219
220
apiRouter.post("/createAlliance.php", createAllianceController);
220
221
apiRouter.post("/createGuild.php", createGuildController);
222
apiRouter.post("/crewShipIdentifySalvage.php", crewShipIdentifySalvageController);
221
223
apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
222
224
apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);
223
225
apiRouter.post("/destroyDojoDeco.php", destroyDojoDecoController);
@@ -426,7 +426,7 @@ export const addItem = async (
426
426
);
427
427
}
428
428
inventoryChanges = {
429
...addCrewShipWeaponSkin(inventory, typeName),
429
...addCrewShipWeaponSkin(inventory, typeName, undefined),
430
430
...occupySlot(inventory, InventorySlot.RJ_COMPONENT_AND_ARMAMENTS, premiumPurchase)
431
431
};
432
432
}
@@ -1107,12 +1107,14 @@ export const addSkin = (
1107
1107
return inventoryChanges;
1108
1108
};
1109
1109
1110
const addCrewShipWeaponSkin = (
1110
export const addCrewShipWeaponSkin = (
1111
1111
inventory: TInventoryDatabaseDocument,
1112
1112
typeName: string,
1113
upgradeFingerprint: string | undefined,
1113
1114
inventoryChanges: IInventoryChanges = {}
1114
1115
): IInventoryChanges => {
1115
const index = inventory.CrewShipWeaponSkins.push({ ItemType: typeName }) - 1;
1116
const index =
1117
inventory.CrewShipWeaponSkins.push({ ItemType: typeName, UpgradeFingerprint: upgradeFingerprint }) - 1;
1116
1118
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1117
1119
inventoryChanges.CrewShipWeaponSkins ??= [];
1118
1120
(inventoryChanges.CrewShipWeaponSkins as IUpgradeClient[]).push(
@@ -1121,6 +1123,22 @@ const addCrewShipWeaponSkin = (
1121
1123
return inventoryChanges;
1122
1124
};
1123
1125
1126
export const addCrewShipSalvagedWeaponSkin = (
1127
inventory: TInventoryDatabaseDocument,
1128
typeName: string,
1129
upgradeFingerprint: string | undefined,
1130
inventoryChanges: IInventoryChanges = {}
1131
): IInventoryChanges => {
1132
const index =
1133
inventory.CrewShipSalvagedWeaponSkins.push({ ItemType: typeName, UpgradeFingerprint: upgradeFingerprint }) - 1;
1134
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1135
inventoryChanges.CrewShipSalvagedWeaponSkins ??= [];
1136
(inventoryChanges.CrewShipSalvagedWeaponSkins as IUpgradeClient[]).push(
1137
inventory.CrewShipSalvagedWeaponSkins[index].toJSON<IUpgradeClient>()
1138
);
1139
return inventoryChanges;
1140
};
1141
1124
1142
const addCrewShip = (
1125
1143
inventory: TInventoryDatabaseDocument,
1126
1144
typeName: string,
@@ -947,15 +947,17 @@ export interface IPersonalTechProjectDatabase {
947
947
State: number;
948
948
ReqCredits: number;
949
949
ItemType: string;
950
ProductCategory?: string;
951
CategoryItemId?: Types.ObjectId;
950
952
ReqItems: ITypeCount[];
951
953
HasContributions?: boolean;
952
954
CompletionDate?: Date;
953
955
}
954
956
955
export interface IPersonalTechProjectClient extends Omit<IPersonalTechProjectDatabase, "CompletionDate"> {
956
CompletionDate?: IMongoDate;
957
ProductCategory?: string;
957
export interface IPersonalTechProjectClient
958
extends Omit<IPersonalTechProjectDatabase, "CategoryItemId" | "CompletionDate"> {
958
959
CategoryItemId?: IOid;
960
CompletionDate?: IMongoDate;
959
961
ItemId: IOid;
960
962
}
961
963
@@ -43,6 +43,7 @@ export type IInventoryChanges = {
43
43
Drones?: IDroneClient[];
44
44
MiscItems?: IMiscItem[];
45
45
EmailItems?: ITypeCount[];
46
CrewShipRawSalvage?: ITypeCount[];
46
47
Nemesis?: Partial<INemesisClient>;
47
48
NewVendorPurchase?: IRecentVendorPurchaseClient; // >= 38.5.0
48
49
RecentVendorPurchases?: IRecentVendorPurchaseClient; // < 38.5.0