WIP: fix: avoid pushing to quest progress in updateQuestStage #2847

Closed
Sainan wants to merge 7 commits from quest-fix into main
4 changed files with 40 additions and 30 deletions

View File

@ -5,6 +5,7 @@ import type { IUpdateQuestRequest } from "../../services/questService.ts";
import { updateQuestKey } from "../../services/questService.ts"; import { updateQuestKey } from "../../services/questService.ts";
import { getInventory } from "../../services/inventoryService.ts"; import { getInventory } from "../../services/inventoryService.ts";
import type { IInventoryChanges } from "../../types/purchaseTypes.ts"; import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
import { sendWsBroadcastTo } from "../../services/wsService.ts";
export const updateQuestController: RequestHandler = async (req, res) => { export const updateQuestController: RequestHandler = async (req, res) => {
const accountId = parseString(req.query.accountId); const accountId = parseString(req.query.accountId);
@ -29,4 +30,5 @@ export const updateQuestController: RequestHandler = async (req, res) => {
await inventory.save(); await inventory.save();
res.send(updateQuestResponse); res.send(updateQuestResponse);
sendWsBroadcastTo(accountId, { update_inventory: true });
}; };

View File

@ -115,7 +115,7 @@ export const manageQuestsController: RequestHandler = async (req, res) => {
if (stage > 0) { if (stage > 0) {
await giveKeyChainStageTriggered(inventory, { await giveKeyChainStageTriggered(inventory, {
KeyChain: questKey.ItemType, KeyChain: questKey.ItemType,
ChainStage: stage - 1 ChainStage: stage
}); });
} }
} }

View File

@ -210,7 +210,7 @@ export const getKeyChainItems = ({ KeyChain, ChainStage }: IKeyChainRequest): st
throw new Error(`KeyChain ${KeyChain} does not contain chain stages`); throw new Error(`KeyChain ${KeyChain} does not contain chain stages`);
} }
const keyChainStage = chainStages[ChainStage]; const keyChainStage = chainStages[ChainStage - 1];
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!keyChainStage) { if (!keyChainStage) {
throw new Error(`KeyChainStage ${ChainStage} not found`); throw new Error(`KeyChainStage ${ChainStage} not found`);

View File

@ -68,26 +68,32 @@ export const updateQuestStage = (
throw new Error(`Progress should always exist when giving keychain triggered items or messages`); throw new Error(`Progress should always exist when giving keychain triggered items or messages`);
} }
const questStage = quest.Progress[ChainStage]; ChainStage -= 1; // They are 1-indexed in the client, but we need 0-indexing
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (ChainStage == quest.Progress.length) {
if (!questStage) { logger.debug(`pushing to quest progress in updateQuestStage`);
const questStageIndex =
quest.Progress.push({ quest.Progress.push({
c: questStageUpdate.c ?? 0, c: 0,
i: questStageUpdate.i ?? false, i: false,
m: questStageUpdate.m ?? false, m: false,
b: questStageUpdate.b ?? [] b: []
}) - 1; });
if (questStageIndex !== ChainStage) { } else if (ChainStage >= quest.Progress.length) {
throw new Error(`Quest stage index mismatch: ${questStageIndex} !== ${ChainStage}`); throw new Error(
} `Quest stage index mismatch: stage is ${ChainStage} but array size is ${quest.Progress.length}`
return; );
} }
// Note that the client may use index 0 as well, e.g. for rising tide's initial inbox message. 'm' is not tracked for it.
if (ChainStage >= 0) {
const questStage = quest.Progress[ChainStage]; // guaranteed in-bounds now
for (const [key, value] of Object.entries(questStageUpdate) as [keyof IQuestStage, number | boolean | any[]][]) { for (const [key, value] of Object.entries(questStageUpdate) as [
keyof IQuestStage,
number | boolean | any[]
][]) {
(questStage[key] as any) = value; (questStage[key] as any) = value;
} }
}
}; };
export const addQuestKey = ( export const addQuestKey = (
@ -157,7 +163,7 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
existingQuestKey.Progress.push(...missingProgress); existingQuestKey.Progress.push(...missingProgress);
} }
for (let i = 0; i < chainStageTotal; i++) { for (let i = 1; i < chainStageTotal; i++) {
const stage = existingQuestKey.Progress[i]; const stage = existingQuestKey.Progress[i];
if (stage.c <= run) { if (stage.c <= run) {
stage.c = run; stage.c = run;
@ -302,7 +308,7 @@ export const giveKeyChainItem = async (
): Promise<IInventoryChanges> => { ): Promise<IInventoryChanges> => {
let inventoryChanges: IInventoryChanges = {}; let inventoryChanges: IInventoryChanges = {};
if (!questKey.Progress?.[keyChainInfo.ChainStage]?.i) { if (!questKey.Progress?.[keyChainInfo.ChainStage - 1]?.i) {
inventoryChanges = await addKeyChainItems(inventory, keyChainInfo); inventoryChanges = await addKeyChainItems(inventory, keyChainInfo);
if (isEmptyObject(inventoryChanges)) { if (isEmptyObject(inventoryChanges)) {
@ -329,6 +335,7 @@ export const giveKeyChainMessage = async (
keyChainInfo: IKeyChainRequest, keyChainInfo: IKeyChainRequest,
questKey: IQuestKeyDatabase questKey: IQuestKeyDatabase
): Promise<void> => { ): Promise<void> => {
if (!questKey.Progress?.[keyChainInfo.ChainStage - 1]?.m) {
const keyChainMessage = getKeyChainMessage(keyChainInfo); const keyChainMessage = getKeyChainMessage(keyChainInfo);
if ((questKey.Progress?.[0]?.c ?? 0) > 0) { if ((questKey.Progress?.[0]?.c ?? 0) > 0) {
@ -339,6 +346,7 @@ export const giveKeyChainMessage = async (
await createMessage(inventory.accountOwnerId, [keyChainMessage]); await createMessage(inventory.accountOwnerId, [keyChainMessage]);
updateQuestStage(inventory, keyChainInfo, { m: true }); updateQuestStage(inventory, keyChainInfo, { m: true });
}
}; };
export const giveKeyChainMissionReward = async ( export const giveKeyChainMissionReward = async (
@ -391,11 +399,11 @@ export const giveKeyChainStageTriggered = async (
const questKey = inventory.QuestKeys.find(qk => qk.ItemType === keyChainInfo.KeyChain); const questKey = inventory.QuestKeys.find(qk => qk.ItemType === keyChainInfo.KeyChain);
if (chainStages && questKey) { if (chainStages && questKey) {
if (chainStages[keyChainInfo.ChainStage].itemsToGiveWhenTriggered.length > 0) { if (chainStages[keyChainInfo.ChainStage - 1].itemsToGiveWhenTriggered.length > 0) {
await giveKeyChainItem(inventory, keyChainInfo, questKey); await giveKeyChainItem(inventory, keyChainInfo, questKey);
} }
if (chainStages[keyChainInfo.ChainStage].messageToSendWhenTriggered) { if (chainStages[keyChainInfo.ChainStage - 1].messageToSendWhenTriggered) {
await giveKeyChainMessage(inventory, keyChainInfo, questKey); await giveKeyChainMessage(inventory, keyChainInfo, questKey);
} }
} }