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: move quest cheats to webui (#963)

Co-authored-by: Sainan <sainan@calamity.inc> Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/963 Co-authored-by: Ordis <134585663+OrdisPrime@users.noreply.github.com> Co-committed-by: Ordis <134585663+OrdisPrime@users.noreply.github.com>

1413a6bc
Ordis <134585663+OrdisPrime@users.noreply.github.com>
提交于

代码差异

10 个文件 +145 -54
Modified config.json.example +0 -2
@@ -13,8 +13,6 @@
13 13 "skipAllDialogue": true,
14 14 "unlockAllScans": true,
15 15 "unlockAllMissions": true,
16 "unlockAllQuests": true,
17 "completeAllQuests": true,
18 16 "infiniteCredits": true,
19 17 "infinitePlatinum": true,
20 18 "infiniteEndo": true,
Modified src/controllers/api/inventoryController.ts +1 -38
@@ -9,7 +9,6 @@ import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inve
9 9 import {
10 10 ExportCustoms,
11 11 ExportFlavour,
12 ExportKeys,
13 12 ExportRegions,
14 13 ExportResources,
15 14 ExportVirtuals
@@ -102,42 +101,6 @@ export const getInventoryResponse = async (
102 101 addString(inventoryResponse.NodeIntrosCompleted, "TeshinHardModeUnlocked");
103 102 }
104 103
105 if (config.unlockAllQuests) {
106 for (const [k, v] of Object.entries(ExportKeys)) {
107 if ("chainStages" in v) {
108 if (!inventoryResponse.QuestKeys.find(quest => quest.ItemType == k)) {
109 inventoryResponse.QuestKeys.push({ ItemType: k });
110 }
111 }
112 }
113 }
114 if (config.completeAllQuests) {
115 for (const quest of inventoryResponse.QuestKeys) {
116 quest.unlock = true;
117 quest.Completed = true;
118
119 let numStages = 1;
120 if (quest.ItemType in ExportKeys && "chainStages" in ExportKeys[quest.ItemType]) {
121 numStages = ExportKeys[quest.ItemType].chainStages!.length;
122 }
123 quest.Progress = [];
124 for (let i = 0; i != numStages; ++i) {
125 quest.Progress.push({
126 c: 0,
127 i: false,
128 m: false,
129 b: []
130 });
131 }
132 }
133
134 inventoryResponse.ArchwingEnabled = true;
135 inventoryResponse.ActiveQuest = ""; //TODO: might need to reconsider this if this does not work long term.
136
137 // Skip "Watch The Maker"
138 addString(inventoryResponse.NodeIntrosCompleted, "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level");
139 }
140
141 104 if (config.unlockAllShipDecorations) {
142 105 inventoryResponse.ShipDecorations = [];
143 106 for (const [uniqueName, item] of Object.entries(ExportResources)) {
@@ -261,7 +224,7 @@ export const getInventoryResponse = async (
261 224 return inventoryResponse;
262 225 };
263 226
264 const addString = (arr: string[], str: string): void => {
227 export const addString = (arr: string[], str: string): void => {
265 228 if (!arr.find(x => x == str)) {
266 229 arr.push(str);
267 230 }
Added src/controllers/custom/manageQuestsController.ts +80 -0
@@ -0,0 +1,80 @@
1 import { addString } from "@/src/controllers/api/inventoryController";
2 import { getInventory } from "@/src/services/inventoryService";
3 import { getAccountIdForRequest } from "@/src/services/loginService";
4 import { addQuestKey, IUpdateQuestRequest, updateQuestKey } from "@/src/services/questService";
5 import { IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes";
6 import { logger } from "@/src/utils/logger";
7 import { RequestHandler } from "express";
8 import { ExportKeys } from "warframe-public-export-plus";
9
10 export const manageQuestsController: RequestHandler = async (req, res) => {
11 const accountId = await getAccountIdForRequest(req);
12 const operation = req.query.operation as
13 | "unlockAll"
14 | "completeAll"
15 | "ResetAll"
16 | "completeAllUnlocked"
17 | "updateKey";
18 const questKeyUpdate = req.body as IUpdateQuestRequest["QuestKeys"];
19
20 const allQuestKeys: string[] = [];
21 for (const [k, v] of Object.entries(ExportKeys)) {
22 if ("chainStages" in v) {
23 allQuestKeys.push(k);
24 }
25 }
26 const inventory = await getInventory(accountId, "QuestKeys NodeIntrosCompleted");
27
28 switch (operation) {
29 case "updateKey": {
30 //TODO: if this is intended to be used, one needs to add a updateQuestKeyMultiple, the game does never intend to do it, so it errors for multiple keys.
31 updateQuestKey(inventory, questKeyUpdate);
32 break;
33 }
34 case "unlockAll": {
35 for (const questKey of allQuestKeys) {
36 addQuestKey(inventory, { ItemType: questKey, Completed: false, unlock: true, Progress: [] });
37 }
38 break;
39 }
40 case "completeAll": {
41 logger.info("completing all quests..");
42 for (const questKey of allQuestKeys) {
43 const chainStageTotal = ExportKeys[questKey].chainStages?.length ?? 0;
44 const Progress = Array(chainStageTotal).fill({ c: 0, i: true, m: true, b: [] } satisfies IQuestStage);
45 const inventoryQuestKey = inventory.QuestKeys.find(qk => qk.ItemType === questKey);
46 if (inventoryQuestKey) {
47 inventoryQuestKey.Completed = true;
48 inventoryQuestKey.Progress = Progress;
49 continue;
50 }
51 addQuestKey(inventory, { ItemType: questKey, Completed: true, unlock: true, Progress: Progress });
52 }
53 inventory.ArchwingEnabled = true;
54 inventory.ActiveQuest = "";
55
56 // Skip "Watch The Maker"
57 addString(inventory.NodeIntrosCompleted, "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level");
58 break;
59 }
60 case "ResetAll": {
61 logger.info("resetting all quests..");
62 for (const questKey of inventory.QuestKeys) {
63 questKey.Completed = false;
64 questKey.Progress = [];
65 }
66 break;
67 }
68 case "completeAllUnlocked": {
69 logger.info("completing all unlocked quests..");
70 for (const questKey of inventory.QuestKeys) {
71 //if (!questKey.unlock) { continue; }
72 questKey.Completed = true;
73 }
74 break;
75 }
76 }
77
78 await inventory.save();
79 res.status(200).end();
80 };
Modified src/routes/custom.ts +2 -0
@@ -16,6 +16,7 @@ import { importController } from "@/src/controllers/custom/importController";
16 16
17 17 import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
18 18 import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
19 import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController";
19 20
20 21 const customRouter = express.Router();
21 22
@@ -32,6 +33,7 @@ customRouter.post("/addCurrency", addCurrencyController);
32 33 customRouter.post("/addItems", addItemsController);
33 34 customRouter.post("/addXp", addXpController);
34 35 customRouter.post("/import", importController);
36 customRouter.post("/manageQuests", manageQuestsController);
35 37
36 38 customRouter.get("/config", getConfigDataController);
37 39 customRouter.post("/config", updateConfigDataController);
Modified src/services/configService.ts +0 -2
@@ -39,8 +39,6 @@ interface IConfig {
39 39 skipAllDialogue?: boolean;
40 40 unlockAllScans?: boolean;
41 41 unlockAllMissions?: boolean;
42 unlockAllQuests?: boolean;
43 completeAllQuests?: boolean;
44 42 infiniteCredits?: boolean;
45 43 infinitePlatinum?: boolean;
46 44 infiniteEndo?: boolean;
Modified src/services/questService.ts +11 -4
@@ -3,7 +3,6 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
3 3 import { IInventoryDatabase, IQuestKeyDatabase, IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes";
4 4 import { logger } from "@/src/utils/logger";
5 5 import { HydratedDocument } from "mongoose";
6 import { config } from "@/src/services/configService";
7 6
8 7 export interface IUpdateQuestRequest {
9 8 QuestKeys: Omit<IQuestKeyDatabase, "CompletionDate">[];
@@ -23,10 +22,10 @@ export const updateQuestKey = (
23 22 throw new Error("more than 1 quest key not supported");
24 23 }
25 24
26 let questKeyIndex = inventory.QuestKeys.findIndex(questKey => questKey.ItemType === questKeyUpdate[0].ItemType);
25 const questKeyIndex = inventory.QuestKeys.findIndex(questKey => questKey.ItemType === questKeyUpdate[0].ItemType);
26
27 27 if (questKeyIndex === -1) {
28 if (!config.unlockAllQuests) throw new Error(`quest key ${questKeyUpdate[0].ItemType} not found`);
29 questKeyIndex = inventory.QuestKeys.push({ ItemType: questKeyUpdate[0].ItemType }) - 1;
28 throw new Error(`quest key ${questKeyUpdate[0].ItemType} not found`);
30 29 }
31 30
32 31 inventory.QuestKeys[questKeyIndex] = questKeyUpdate[0];
@@ -63,3 +62,11 @@ export const updateQuestStage = (
63 62
64 63 Object.assign(questStage, questStageUpdate);
65 64 };
65
66 export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQuestKeyDatabase): void => {
67 if (inventory.QuestKeys.some(q => q.ItemType === questKey.ItemType)) {
68 logger.error(`quest key ${questKey.ItemType} already exists`);
69 return;
70 }
71 inventory.QuestKeys.push(questKey);
72 };
Modified static/webui/index.html +28 -8
@@ -410,6 +410,27 @@
410 410 </div>
411 411 </div>
412 412 </div>
413 <div data-route="/webui/quests" data-title="Quests | OpenWF WebUI">
414 <div class="card mb-3">
415 <h5 class="card-header" data-loc="quests_list"></h5>
416 <div class="card-body">
417 <table class="table table-hover w-100">
418 <tbody id="active-quests"></tbody>
419 </table>
420 </div>
421 </div>
422 <div class="card mb-3">
423 <h5 class="card-header" data-loc="quests_Actions"></h5>
424 <div class="card-body">
425 <div class="mb-2 d-flex flex-wrap gap-2">
426 <button class="btn btn-primary" onclick="doQuestUpdate('unlockAll');" data-loc="quests_UnlockAll"></button>
427 <button class="btn btn-primary" onclick="doQuestUpdate('completeAll');" data-loc="quests_CompleteAll"></button>
428 <button class="btn btn-primary" onclick="doQuestUpdate('completeAllUnlocked');" data-loc="quests_CompleteAllUnlocked"></button>
429 <button class="btn btn-primary" onclick="doQuestUpdate('ResetAll');" data-loc="quests_ResetAll"></button>
430 </div>
431 </div>
432 </div>
433 </div>
413 434 <div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
414 435 <div class="row g-3">
415 436 <div class="col-md-6">
@@ -436,14 +457,6 @@
436 457 <input class="form-check-input" type="checkbox" id="unlockAllMissions" />
437 458 <label class="form-check-label" for="unlockAllMissions" data-loc="cheats_unlockAllMissions"></label>
438 459 </div>
439 <div class="form-check">
440 <input class="form-check-input" type="checkbox" id="unlockAllQuests" />
441 <label class="form-check-label" for="unlockAllQuests" data-loc="cheats_unlockAllQuests"></label>
442 </div>
443 <div class="form-check">
444 <input class="form-check-input" type="checkbox" id="completeAllQuests" />
445 <label class="form-check-label" for="completeAllQuests" data-loc="cheats_completeAllQuests"></label>
446 </div>
447 460 <div class="form-check">
448 461 <input class="form-check-input" type="checkbox" id="infiniteCredits" />
449 462 <label class="form-check-label" for="infiniteCredits" data-loc="cheats_infiniteCredits"></label>
@@ -524,6 +537,13 @@
524 537 <button class="btn btn-primary" type="submit" data-loc="cheats_changeButton"></button>
525 538 </div>
526 539 </form>
540 <h5 class="mt-3" data-loc="cheats_quests"></h6>
541 <div class="mb-2 d-flex flex-wrap gap-2">
542 <button class="btn btn-primary" onclick="doQuestUpdate('unlockAll');" data-loc="cheats_quests_UnlockAll"></button>
543 <button class="btn btn-primary" onclick="doQuestUpdate('completeAll');" data-loc="cheats_quests_CompleteAll"></button>
544 <button class="btn btn-primary" onclick="doQuestUpdate('completeAllUnlocked');" data-loc="cheats_quests_CompleteAllUnlocked"></button>
545 <button class="btn btn-primary" onclick="doQuestUpdate('ResetAll');" data-loc="cheats_quests_ResetAll"></button>
546 </div>
527 547 </div>
528 548 </div>
529 549 </div>
Modified static/webui/script.js +9 -0
@@ -1153,3 +1153,12 @@ function doAddCurrency(currency) {
1153 1153 updateInventory();
1154 1154 });
1155 1155 }
1156
1157 function doQuestUpdate(operation) {
1158 $.post({
1159 url: "/custom/manageQuests?" + window.authz + "&operation=" + operation,
1160 contentType: "application/json"
1161 }).then(function () {
1162 updateInventory();
1163 });
1164 }
Modified static/webui/translations/en.js +7 -0
@@ -45,6 +45,7 @@ dict = {
45 45 navbar_deleteAccount: `Delete Account`,
46 46 navbar_inventory: `Inventory`,
47 47 navbar_mods: `Mods`,
48 navbar_quests: `Quests`,
48 49 navbar_cheats: `Cheats`,
49 50 navbar_import: `Import`,
50 51 inventory_addItems: `Add Items`,
@@ -72,6 +73,7 @@ dict = {
72 73 inventory_bulkRankUpSpaceWeapons: `Max Rank All Archwing Weapons`,
73 74 inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
74 75 inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
76
75 77 currency_RegularCredits: `Credits`,
76 78 currency_PremiumCredits: `Platinum`,
77 79 currency_FusionPoints: `Endo`,
@@ -115,6 +117,11 @@ dict = {
115 117 cheats_changeSupportedSyndicate: `Supported syndicate`,
116 118 cheats_changeButton: `Change`,
117 119 cheats_none: `None`,
120 cheats_quests: `Quests`,
121 cheats_quests_UnlockAll: `Unlock All Quests`,
122 cheats_quests_CompleteAll: `Complete All Quests`,
123 cheats_quests_CompleteAllUnlocked: `Complete All Unlocked Quests`,
124 cheats_quests_ResetAll: `Reset All Quests`,
118 125 import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
119 126 import_submit: `Submit`
120 127 };
Modified static/webui/translations/ru.js +7 -0
@@ -46,6 +46,7 @@ dict = {
46 46 navbar_deleteAccount: `Удалить аккаунт`,
47 47 navbar_inventory: `Инвентарь`,
48 48 navbar_mods: `Моды`,
49 navbar_quests: `[UNTRANSLATED] Quests`,
49 50 navbar_cheats: `Читы`,
50 51 navbar_import: `Импорт`,
51 52 inventory_addItems: `Добавить предметы`,
@@ -73,6 +74,7 @@ dict = {
73 74 inventory_bulkRankUpSpaceWeapons: `Максимальный ранг всего оружия арчвингов`,
74 75 inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
75 76 inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
77
76 78 currency_RegularCredits: `Кредиты`,
77 79 currency_PremiumCredits: `Платина`,
78 80 currency_FusionPoints: `Эндо`,
@@ -116,6 +118,11 @@ dict = {
116 118 cheats_changeSupportedSyndicate: `Поддерживаемый синдикат`,
117 119 cheats_changeButton: `Изменить`,
118 120 cheats_none: `Отсутствует`,
121 cheats_quests: `[UNTRANSLATED] Quests`,
122 cheats_quests_UnlockAll: `[UNTRANSLATED] Unlock All Quests`,
123 cheats_quests_CompleteAll: `[UNTRANSLATED] Complete All Quests`,
124 cheats_quests_CompleteAllUnlocked: `[UNTRANSLATED] Complete All Unlocked Quests`,
125 cheats_quests_ResetAll: `[UNTRANSLATED] Reset All Quests`,
119 126 import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
120 127 import_submit: `Submit`
121 128 };