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: thousand-year fish (#3949)

Closes #3933 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/3949 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>

cba2c9fd
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

6 个文件 +66 -4
Modified src/controllers/custom/unlockAllScansController.ts +13 -2
@@ -3,7 +3,12 @@ import allScans from "../../../static/fixed_responses/allScans.json" with { type
3 3 import { ExportCodex, ExportEnemies } from "warframe-public-export-plus";
4 4 import { getAccountIdForRequest } from "../../services/loginService.ts";
5 5 import { getStats } from "../../services/statsService.ts";
6 import { addShipDecorations, getInventory, updateIncentiveStates } from "../../services/inventoryService.ts";
6 import {
7 addShipDecorations,
8 getInventory,
9 giveThousandYearFishDeco,
10 updateIncentiveStates
11 } from "../../services/inventoryService.ts";
7 12 import { getShipDecoByNameTag } from "../../services/itemDataService.ts";
8 13 import { broadcastInventoryUpdate } from "../../services/wsService.ts";
9 14
@@ -11,7 +16,10 @@ export const unlockAllScansController: RequestHandler = async (req, res) => {
11 16 const accountId = await getAccountIdForRequest(req);
12 17 const [stats, inventory] = await Promise.all([
13 18 getStats(accountId),
14 getInventory(accountId, "ChallengeProgress CollectibleSeries LoreFragmentScans ShipDecorations")
19 getInventory(
20 accountId,
21 "ChallengeProgress CollectibleSeries LoreFragmentScans ShipDecorations receivedThousandYearFishDeco accountOwnerId"
22 )
15 23 ]);
16 24
17 25 // Unlock all enemy & object scans
@@ -158,6 +166,9 @@ export const unlockAllScansController: RequestHandler = async (req, res) => {
158 166 ItemType
159 167 });
160 168 }
169 if (!inventory.receivedThousandYearFishDeco) {
170 await giveThousandYearFishDeco(inventory); // needs accountOwnerId
171 }
161 172
162 173 await Promise.all([stats.save(), inventory.save()]);
163 174 res.end();
Modified src/models/inventoryModels/inventoryModel.ts +2 -0
@@ -1753,6 +1753,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1753 1753 Ships: { type: [Schema.Types.ObjectId], ref: "Ships" },
1754 1754 // /Lotus/Types/Items/ShipDecos/
1755 1755 ShipDecorations: [typeCountSchema],
1756 receivedThousandYearFishDeco: Boolean,
1756 1757
1757 1758 //Railjack/Components(https://warframe.fandom.com/wiki/Railjack/Components)
1758 1759 CrewShipRawSalvage: [typeCountSchema],
@@ -2037,6 +2038,7 @@ inventorySchema.set("toJSON", {
2037 2038 delete returnedObject.NemesisTaxedCredits;
2038 2039 delete returnedObject.duviriSeedRefresh;
2039 2040 delete returnedObject.HybridFusionTreasures;
2041 delete returnedObject.receivedThousandYearFishDeco;
2040 2042
2041 2043 const inventoryDatabase = returnedObject as Partial<IInventoryDatabase>;
2042 2044 const inventoryResponse = returnedObject as IInventoryClient;
Modified src/services/importService.ts +4 -1
@@ -88,7 +88,7 @@ import type {
88 88 import { fromMongoDate, fromOid } from "../helpers/inventoryHelpers.ts";
89 89 import { getRecipe } from "./itemDataService.ts";
90 90 import { logger } from "../utils/logger.ts";
91 import { migrateFusionTreasures } from "./inventoryService.ts";
91 import { isEligibleForThousandYearFishDeco, migrateFusionTreasures } from "./inventoryService.ts";
92 92
93 93 const convertOptionalDate = (value: IMongoDateWithLegacySupport | undefined): Date | undefined => {
94 94 return value ? fromMongoDate(value) : undefined;
@@ -506,6 +506,9 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
506 506 }
507 507 if (client.LoreFragmentScans !== undefined) {
508 508 db.LoreFragmentScans = client.LoreFragmentScans;
509 if (!db.receivedThousandYearFishDeco && isEligibleForThousandYearFishDeco(db)) {
510 db.receivedThousandYearFishDeco = true;
511 }
509 512 }
510 513 for (const key of ["PendingSpectreLoadouts", "SpectreLoadouts"] as const) {
511 514 if (client[key] !== undefined) {
Modified src/services/inventoryService.ts +40 -0
@@ -3099,6 +3099,46 @@ export const updateEntratiVault = (inventory: TInventoryDatabaseDocument): void
3099 3099 }
3100 3100 };
3101 3101
3102 export const isEligibleForThousandYearFishDeco = (inventory: TInventoryDatabaseDocument): boolean => {
3103 const lfsTypes = new Set<string>(inventory.LoreFragmentScans.map(x => x.ItemType));
3104 return (
3105 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentA") &&
3106 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentB") &&
3107 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentC") &&
3108 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentD") &&
3109 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentE") &&
3110 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentF") &&
3111 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentG") &&
3112 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentH") &&
3113 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentI") &&
3114 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentJ") &&
3115 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentK") &&
3116 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentL") &&
3117 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentM") &&
3118 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentN") &&
3119 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentO") &&
3120 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentP") &&
3121 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentQ") &&
3122 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentR") &&
3123 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentS") &&
3124 lfsTypes.has("/Lotus/Types/Lore/Fragments/EidolonFragments/EidolonFragmentT")
3125 );
3126 };
3127
3128 export const giveThousandYearFishDeco = async (inventory: TInventoryDatabaseDocument): Promise<void> => {
3129 inventory.receivedThousandYearFishDeco = true;
3130 await createMessage(inventory.accountOwnerId, [
3131 {
3132 sndr: "/Lotus/Language/Npcs/Onkko",
3133 icon: "/Lotus/Interface/Icons/Npcs/Ostron/Onkko.png",
3134 sub: "/Lotus/Language/Messages/EidolonCollectibleRewardTitle",
3135 msg: "/Lotus/Language/Messages/EidolonCollectibleRewardBody",
3136 att: ["/Lotus/Types/Items/ShipDecos/LisetPropOstStoneFish"],
3137 highPriority: true
3138 }
3139 ]);
3140 };
3141
3102 3142 export const ensureUserHasFounderHonoria = async (inventory: TInventoryDatabaseDocument): Promise<void> => {
3103 3143 if (!inventory.FlavourItems.some(x => x.ItemType == "/Lotus/Types/Items/Titles/FounderLvl1Title")) {
3104 3144 const eligibleItems = [
Modified src/services/missionInventoryUpdateService.ts +5 -0
@@ -47,6 +47,8 @@ import {
47 47 getDialogue,
48 48 giveNemesisPetRecipe,
49 49 giveNemesisWeaponRecipe,
50 giveThousandYearFishDeco,
51 isEligibleForThousandYearFishDeco,
50 52 updateCurrency,
51 53 updateEntratiVault,
52 54 updateIncentiveStates,
@@ -476,6 +478,9 @@ export const addMissionInventoryUpdates = async (
476 478 }
477 479 case "LoreFragmentScans":
478 480 addLoreFragmentScans(inventory, value);
481 if (!inventory.receivedThousandYearFishDeco && isEligibleForThousandYearFishDeco(inventory)) {
482 await giveThousandYearFishDeco(inventory);
483 }
479 484 break;
480 485 case "LibraryScans":
481 486 value.forEach(scan => {
Modified src/types/inventoryTypes/inventoryTypes.ts +2 -1
@@ -167,6 +167,8 @@ export interface IInventoryDatabase
167 167 DeathSquadPoints?: number;
168 168 NemesisTaxedCredits?: number;
169 169 duviriSeedRefresh?: Date;
170 HybridFusionTreasures: IHybridFusionTreasure[]; // SNS-specific in-database format to support both modern & legacy clients
171 receivedThousandYearFishDeco?: true; // placed decos are not in inventory, hence this boolean
170 172
171 173 Created: Date;
172 174 CurrentLoadOutIds: Types.ObjectId[];
@@ -211,7 +213,6 @@ export interface IInventoryDatabase
211 213 ChallengeInstanceStates?: IChallengeInstanceStateDatabase[];
212 214 PeriodicMissionCompletions: IPeriodicMissionCompletionDatabase[];
213 215 FusionTreasures?: IFusionTreasure[];
214 HybridFusionTreasures: IHybridFusionTreasure[]; // SNS-specific in-database format to support both modern & legacy clients
215 216 }
216 217
217 218 export interface IQuestKeyDatabase {