XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 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
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

7 个文件 +158 -37
Added src/controllers/api/crewShipIdentifySalvageController.ts +41 -0
@@ -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 }
Modified src/controllers/api/guildTechController.ts +83 -31
@@ -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 };
Modified src/models/inventoryModels/inventoryModel.ts +5 -0
@@ -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 }
Modified src/routes/api.ts +2 -0
@@ -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);
Modified src/services/inventoryService.ts +21 -3
@@ -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,
Modified src/types/inventoryTypes/inventoryTypes.ts +5 -3
@@ -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
Modified src/types/purchaseTypes.ts +1 -0
@@ -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