返回提交历史
Added
src/controllers/api/completeCalendarEventController.ts
+41
-0
Modified
src/models/inventoryModels/inventoryModel.ts
+6
-6
Modified
src/routes/api.ts
+2
-0
Modified
src/services/inventoryService.ts
+37
-17
Modified
src/services/missionInventoryUpdateService.ts
+10
-0
Modified
src/services/worldStateService.ts
+1
-1
Modified
src/types/inventoryTypes/inventoryTypes.ts
+5
-4
Modified
src/types/requestTypes.ts
+1
-0
Modified
src/types/worldStateTypes.ts
+1
-1
XFEstudio/XFESpaceNinjaServer
feat: calendar progress (#1830)
Closes #1775 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1830 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
fd7f4c9e
代码差异
9 个文件
+104
-29
@@ -0,0 +1,41 @@
1
import { getCalendarProgress, getInventory } from "@/src/services/inventoryService";
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
4
import { getWorldState } from "@/src/services/worldStateService";
5
import { IInventoryChanges } from "@/src/types/purchaseTypes";
6
import { RequestHandler } from "express";
7
8
// GET request; query parameters: CompletedEventIdx=0&Iteration=4&Version=19&Season=CST_SUMMER
9
export const completeCalendarEventController: RequestHandler = async (req, res) => {
10
const accountId = await getAccountIdForRequest(req);
11
const inventory = await getInventory(accountId);
12
const calendarProgress = getCalendarProgress(inventory);
13
const currentSeason = getWorldState().KnownCalendarSeasons[0];
14
let inventoryChanges: IInventoryChanges = {};
15
let dayIndex = 0;
16
for (const day of currentSeason.Days) {
17
if (day.events.length == 0 || day.events[0].type != "CET_CHALLENGE") {
18
if (dayIndex == calendarProgress.SeasonProgress.LastCompletedDayIdx) {
19
if (day.events.length != 0) {
20
const selection = day.events[parseInt(req.query.CompletedEventIdx as string)];
21
if (selection.type == "CET_REWARD") {
22
inventoryChanges = (await handleStoreItemAcquisition(selection.reward!, inventory))
23
.InventoryChanges;
24
} else if (selection.type == "CET_UPGRADE") {
25
calendarProgress.YearProgress.Upgrades.push(selection.upgrade!);
26
} else if (selection.type != "CET_PLOT") {
27
throw new Error(`unexpected selection type: ${selection.type}`);
28
}
29
}
30
break;
31
}
32
++dayIndex;
33
}
34
}
35
calendarProgress.SeasonProgress.LastCompletedDayIdx++;
36
await inventory.save();
37
res.json({
38
InventoryChanges: inventoryChanges,
39
CalendarProgress: inventory.CalendarProgress
40
});
41
};
@@ -1125,15 +1125,15 @@ const CustomMarkersSchema = new Schema<ICustomMarkers>(
1125
1125
const calenderProgressSchema = new Schema<ICalendarProgress>(
1126
1126
{
1127
1127
Version: { type: Number, default: 19 },
1128
Iteration: { type: Number, default: 2 },
1128
Iteration: { type: Number, required: true },
1129
1129
YearProgress: {
1130
Upgrades: { type: [] }
1130
Upgrades: { type: [String], default: [] }
1131
1131
},
1132
1132
SeasonProgress: {
1133
SeasonType: String,
1134
LastCompletedDayIdx: { type: Number, default: -1 },
1135
LastCompletedChallengeDayIdx: { type: Number, default: -1 },
1136
ActivatedChallenges: []
1133
SeasonType: { type: String, required: true },
1134
LastCompletedDayIdx: { type: Number, default: 0 },
1135
LastCompletedChallengeDayIdx: { type: Number, default: 0 },
1136
ActivatedChallenges: { type: [String], default: [] }
1137
1137
}
1138
1138
},
1139
1139
{ _id: false }
@@ -19,6 +19,7 @@ import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompl
19
19
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
20
20
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
21
21
import { clearNewEpisodeRewardController } from "@/src/controllers/api/clearNewEpisodeRewardController";
22
import { completeCalendarEventController } from "@/src/controllers/api/completeCalendarEventController";
22
23
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
23
24
import { confirmAllianceInvitationController } from "@/src/controllers/api/confirmAllianceInvitationController";
24
25
import { confirmGuildInvitationGetController, confirmGuildInvitationPostController } from "@/src/controllers/api/confirmGuildInvitationController";
@@ -158,6 +159,7 @@ apiRouter.get("/changeDojoRoot.php", changeDojoRootController);
158
159
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
159
160
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
160
161
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
162
apiRouter.get("/completeCalendarEvent.php", completeCalendarEventController);
161
163
apiRouter.get("/confirmAllianceInvitation.php", confirmAllianceInvitationController);
162
164
apiRouter.get("/confirmGuildInvitation.php", confirmGuildInvitationGetController);
163
165
apiRouter.get("/credits.php", creditsController);
@@ -18,7 +18,6 @@ import {
18
18
IKubrowPetEggDatabase,
19
19
IKubrowPetEggClient,
20
20
ILibraryDailyTaskInfo,
21
ICalendarProgress,
22
21
IDroneClient,
23
22
IUpgradeClient,
24
23
TPartialStartingGear,
@@ -26,7 +25,8 @@ import {
26
25
ICrewMemberClient,
27
26
Status,
28
27
IKubrowPetDetailsDatabase,
29
ITraits
28
ITraits,
29
ICalendarProgress
30
30
} from "@/src/types/inventoryTypes/inventoryTypes";
31
31
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
32
32
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
@@ -78,6 +78,7 @@ import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
78
78
import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from "./rngService";
79
79
import { createMessage } from "./inboxService";
80
80
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
81
import { getWorldState } from "./worldStateService";
81
82
82
83
export const createInventory = async (
83
84
accountOwnerId: Types.ObjectId,
@@ -91,7 +92,6 @@ export const createInventory = async (
91
92
});
92
93
93
94
inventory.LibraryAvailableDailyTaskInfo = createLibraryDailyTask();
94
inventory.CalendarProgress = createCalendar();
95
95
inventory.RewardSeed = generateRewardSeed();
96
96
inventory.DuviriInfo = {
97
97
Seed: generateRewardSeed(),
@@ -1756,20 +1756,6 @@ export const createLibraryDailyTask = (): ILibraryDailyTaskInfo => {
1756
1756
};
1757
1757
};
1758
1758
1759
const createCalendar = (): ICalendarProgress => {
1760
return {
1761
Version: 19,
1762
Iteration: 2,
1763
YearProgress: { Upgrades: [] },
1764
SeasonProgress: {
1765
SeasonType: "CST_SPRING",
1766
LastCompletedDayIdx: -1,
1767
LastCompletedChallengeDayIdx: -1,
1768
ActivatedChallenges: []
1769
}
1770
};
1771
};
1772
1773
1759
export const setupKahlSyndicate = (inventory: TInventoryDatabaseDocument): void => {
1774
1760
inventory.Affiliations.push({
1775
1761
Title: 1,
@@ -1806,3 +1792,37 @@ export const cleanupInventory = (inventory: TInventoryDatabaseDocument): void =>
1806
1792
LibrarySyndicate.FreeFavorsEarned = undefined;
1807
1793
}
1808
1794
};
1795
1796
export const getCalendarProgress = (inventory: TInventoryDatabaseDocument): ICalendarProgress => {
1797
const currentSeason = getWorldState().KnownCalendarSeasons[0];
1798
1799
if (!inventory.CalendarProgress) {
1800
inventory.CalendarProgress = {
1801
Version: 19,
1802
Iteration: currentSeason.YearIteration,
1803
YearProgress: {
1804
Upgrades: []
1805
},
1806
SeasonProgress: {
1807
SeasonType: currentSeason.Season,
1808
LastCompletedDayIdx: 0,
1809
LastCompletedChallengeDayIdx: 0,
1810
ActivatedChallenges: []
1811
}
1812
};
1813
}
1814
1815
const yearRolledOver = inventory.CalendarProgress.Iteration != currentSeason.YearIteration;
1816
if (yearRolledOver) {
1817
inventory.CalendarProgress.Iteration = currentSeason.YearIteration;
1818
inventory.CalendarProgress.YearProgress.Upgrades = [];
1819
}
1820
if (yearRolledOver || inventory.CalendarProgress.SeasonProgress.SeasonType != currentSeason.Season) {
1821
inventory.CalendarProgress.SeasonProgress.SeasonType = currentSeason.Season;
1822
inventory.CalendarProgress.SeasonProgress.LastCompletedDayIdx = -1;
1823
inventory.CalendarProgress.SeasonProgress.LastCompletedChallengeDayIdx = -1;
1824
inventory.CalendarProgress.SeasonProgress.ActivatedChallenges = [];
1825
}
1826
1827
return inventory.CalendarProgress;
1828
};
@@ -33,6 +33,7 @@ import {
33
33
addStanding,
34
34
combineInventoryChanges,
35
35
generateRewardSeed,
36
getCalendarProgress,
36
37
updateCurrency,
37
38
updateSyndicate
38
39
} from "@/src/services/inventoryService";
@@ -560,6 +561,15 @@ export const addMissionInventoryUpdates = async (
560
561
}
561
562
break;
562
563
}
564
case "CalendarProgress": {
565
const calendarProgress = getCalendarProgress(inventory);
566
for (const progress of value) {
567
const challengeName = progress.challenge.substring(progress.challenge.lastIndexOf("/") + 1);
568
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx++;
569
calendarProgress.SeasonProgress.ActivatedChallenges.push(challengeName);
570
}
571
break;
572
}
563
573
default:
564
574
// Equipment XP updates
565
575
if (equipmentKeys.includes(key as TEquipmentKey)) {
@@ -683,7 +683,7 @@ const getCalendarSeason = (week: number): ICalendarSeason => {
683
683
Activation: { $date: { $numberLong: weekStart.toString() } },
684
684
Expiry: { $date: { $numberLong: weekEnd.toString() } },
685
685
Days: eventDays,
686
Season: ["CST_WINTER", "CST_SPRING", "CST_SUMMER", "CST_FALL"][seasonIndex],
686
Season: (["CST_WINTER", "CST_SPRING", "CST_SUMMER", "CST_FALL"] as const)[seasonIndex],
687
687
YearIteration: Math.trunc(week / 4),
688
688
Version: 19,
689
689
UpgradeAvaliabilityRequirements: ["/Lotus/Upgrades/Calendar/1999UpgradeApplicationRequirement"]
@@ -353,7 +353,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
353
353
DeathSquadable: boolean;
354
354
EndlessXP?: IEndlessXpProgress[];
355
355
DialogueHistory?: IDialogueHistoryClient;
356
CalendarProgress: ICalendarProgress;
356
CalendarProgress?: ICalendarProgress;
357
357
SongChallenges?: ISongChallenge[];
358
358
EntratiVaultCountLastPeriod?: number;
359
359
EntratiVaultCountResetDate?: IMongoDate;
@@ -1193,17 +1193,18 @@ export interface IMarker {
1193
1193
z: number;
1194
1194
showInHud: boolean;
1195
1195
}
1196
1196
1197
export interface ISeasonProgress {
1197
SeasonType: "CST_UNDEFINED" | "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
1198
SeasonType: "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
1198
1199
LastCompletedDayIdx: number;
1199
1200
LastCompletedChallengeDayIdx: number;
1200
ActivatedChallenges: unknown[];
1201
ActivatedChallenges: string[];
1201
1202
}
1202
1203
1203
1204
export interface ICalendarProgress {
1204
1205
Version: number;
1205
1206
Iteration: number;
1206
YearProgress: { Upgrades: unknown[] };
1207
YearProgress: { Upgrades: string[] };
1207
1208
SeasonProgress: ISeasonProgress;
1208
1209
}
1209
1210
@@ -44,6 +44,7 @@ export type IMissionInventoryUpdateRequest = {
44
44
45
45
SyndicateId?: string;
46
46
SortieId?: string;
47
CalendarProgress?: { challenge: string }[];
47
48
SeasonChallengeCompletions?: ISeasonChallenge[];
48
49
AffiliationChanges?: IAffiliationChange[];
49
50
crossPlaySetting?: string;
@@ -133,7 +133,7 @@ export interface ISeasonChallenge {
133
133
export interface ICalendarSeason {
134
134
Activation: IMongoDate;
135
135
Expiry: IMongoDate;
136
Season: string; // "CST_UNDEFINED" | "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL"
136
Season: "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
137
137
Days: ICalendarDay[];
138
138
YearIteration: number;
139
139
Version: number;