feat: initial foundry for U8 #3014

Merged
Sainan merged 1 commits from AMelonInsideLemon/SpaceNinjaServer:u8-foundry into main 2025-11-10 23:50:52 -08:00
4 changed files with 82 additions and 22 deletions
Showing only changes of commit 79c2431e37 - Show all commits

View File

@@ -0,0 +1,24 @@
import { getAccountIdForRequest } from "../../services/loginService.ts";
import type { RequestHandler } from "express";
import { getInventory } from "../../services/inventoryService.ts";
export const checkPendingRecipesController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId, "PendingRecipes");
const now = Date.now();
const resp: ICheckPendingRecipesResponse = {
PendingRecipes: inventory.PendingRecipes.map(recipe => ({
ItemType: recipe.ItemType,
SecondsRemaining: Math.max(0, Math.floor((recipe.CompletionDate.getTime() - now) / 1000))
}))
};
res.send(resp);
};
interface ICheckPendingRecipesResponse {
PendingRecipes: {
ItemType: string;
SecondsRemaining: number;
}[];
}

View File

@@ -38,22 +38,47 @@ interface IClaimCompletedRecipeResponse {
}
export const claimCompletedRecipeController: RequestHandler = async (req, res) => {
const claimCompletedRecipeRequest = getJSONfromString<IClaimCompletedRecipeRequest>(String(req.body));
const account = await getAccountForRequest(req);
const inventory = await getInventory(account._id.toString());
const resp: IClaimCompletedRecipeResponse = {
InventoryChanges: {}
};
for (const recipeId of claimCompletedRecipeRequest.RecipeIds) {
const pendingRecipe = inventory.PendingRecipes.id(fromOid(recipeId));
if (!pendingRecipe) {
throw new Error(`no pending recipe found with id ${fromOid(recipeId)}`);
}
if (!req.query.recipeName) {
const claimCompletedRecipeRequest = getJSONfromString<IClaimCompletedRecipeRequest>(String(req.body));
for (const recipeId of claimCompletedRecipeRequest.RecipeIds) {
const pendingRecipe = inventory.PendingRecipes.id(fromOid(recipeId));
if (!pendingRecipe) {
throw new Error(`no pending recipe found with id ${fromOid(recipeId)}`);
}
//check recipe is indeed ready to be completed
// if (pendingRecipe.CompletionDate > new Date()) {
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
// }
//check recipe is indeed ready to be completed
// if (pendingRecipe.CompletionDate > new Date()) {
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
// }
inventory.PendingRecipes.pull(pendingRecipe._id);
const recipe = getRecipe(pendingRecipe.ItemType);
if (!recipe) {
throw new Error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
}
if (req.query.cancel) {
const inventoryChanges: IInventoryChanges = {};
await refundRecipeIngredients(inventory, inventoryChanges, recipe, pendingRecipe);
await inventory.save();
res.json(inventoryChanges); // Not a bug: In the specific case of cancelling a recipe, InventoryChanges are expected to be the root.
return;
}
await claimCompletedRecipe(account, inventory, recipe, pendingRecipe, resp, req.query.rush);
}
} else {
const recipeName = String(req.query.recipeName); // U8
const pendingRecipe = inventory.PendingRecipes.find(r => r.ItemType == recipeName);
if (!pendingRecipe) {
throw new Error(`no pending recipe found with ItemType ${recipeName}`);
}
inventory.PendingRecipes.pull(pendingRecipe._id);
@@ -61,16 +86,14 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
if (!recipe) {
throw new Error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
}
if (req.query.cancel) {
const inventoryChanges: IInventoryChanges = {};
await refundRecipeIngredients(inventory, inventoryChanges, recipe, pendingRecipe);
await inventory.save();
res.json(inventoryChanges); // Not a bug: In the specific case of cancelling a recipe, InventoryChanges are expected to be the root.
return;
}
await claimCompletedRecipe(account, inventory, recipe, pendingRecipe, resp, req.query.rush);
await claimCompletedRecipe(
account,
inventory,
recipe,
pendingRecipe,
resp,
req.path.includes("instantCompleteRecipe.php")
);
}
await inventory.save();
res.json(resp);

View File

@@ -24,7 +24,8 @@ export const startRecipeController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const recipeName = startRecipeRequest.RecipeName;
let recipeName = startRecipeRequest.RecipeName;
if (req.query.recipeName) recipeName = String(req.query.recipeName); // U8
const recipe = getRecipe(recipeName);
if (!recipe) {
@@ -65,7 +66,16 @@ export const startRecipeController: RequestHandler = async (req, res) => {
freeUpSlot(inventory, InventorySlot.WEAPONS);
}
} else {
await addItem(inventory, recipe.ingredients[i].ItemType, recipe.ingredients[i].ItemCount * -1);
const itemType = recipe.ingredients[i].ItemType;
const itemCount = recipe.ingredients[i].ItemCount;
const inventoryItem = inventory.MiscItems.find(i => i.ItemType === itemType);
if (inventoryItem && inventoryItem.ItemCount >= itemCount) {
await addItem(inventory, itemType, itemCount * -1);
} else {
throw new Error(
`insufficient ${itemType} (in inventory ${inventoryItem?.ItemCount} - needed ${itemCount}) for recipe ${recipeName}`
);
}
}
}

View File

@@ -20,6 +20,7 @@ import { cancelGuildAdvertisementController } from "../controllers/api/cancelGui
import { changeDojoRootController } from "../controllers/api/changeDojoRootController.ts";
import { changeGuildRankController } from "../controllers/api/changeGuildRankController.ts";
import { checkDailyMissionBonusController } from "../controllers/api/checkDailyMissionBonusController.ts";
import { checkPendingRecipesController } from "../controllers/api/checkPendingRecipesController.ts";
import { claimCompletedRecipeController } from "../controllers/api/claimCompletedRecipeController.ts";
import { claimJunctionChallengeRewardController } from "../controllers/api/claimJunctionChallengeRewardController.ts";
import { claimLibraryDailyTaskRewardController } from "../controllers/api/claimLibraryDailyTaskRewardController.ts";
@@ -184,6 +185,7 @@ apiRouter.get("/cancelGuildAdvertisement.php", cancelGuildAdvertisementControlle
apiRouter.get("/changeDojoRoot.php", changeDojoRootController);
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
apiRouter.get("/checkPendingRecipes.php", checkPendingRecipesController); // U8
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
apiRouter.get("/completeCalendarEvent.php", completeCalendarEventController);
apiRouter.get("/confirmAllianceInvitation.php", confirmAllianceInvitationController);
@@ -305,6 +307,7 @@ apiRouter.post("/guildTech.php", guildTechController);
apiRouter.post("/hostSession.php", hostSessionController);
apiRouter.post("/hubBlessing.php", hubBlessingController);
apiRouter.post("/infestedFoundry.php", infestedFoundryController);
apiRouter.post("/instantCompleteRecipe.php", claimCompletedRecipeController); // U8
apiRouter.post("/inventorySlots.php", inventorySlotsController);
apiRouter.post("/joinSession.php", joinSessionController);
apiRouter.post("/login.php", loginController);