XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFESpaceNinjaServer

feat(clan): solar rail research (#3583)

idk how alliance is supposed to acquire solar rail bp Closes #3560 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/3583 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>

2ea6148b
AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
提交于

代码差异

6 个文件 +81 -27
Added src/controllers/api/getVaultController.ts +27 -0
@@ -0,0 +1,27 @@
1 import type { RequestHandler } from "express";
2 import { getAccountForRequest } from "../../services/loginService.ts";
3 import { getInventory } from "../../services/inventoryService.ts";
4 import { getAllianceVault, getGuildForRequestEx, getGuildVault } from "../../services/guildService.ts";
5 import { Alliance } from "../../models/guildModel.ts";
6
7 export const getVaultController: RequestHandler = async (req, res) => {
8 const account = await getAccountForRequest(req);
9 const inventory = await getInventory(account._id, "GuildId");
10 const guild = await getGuildForRequestEx(req, inventory);
11
12 const allianceId = req.query.allianceId as string;
13 if (!allianceId) {
14 res.json({ Vault: getGuildVault(guild) });
15 return;
16 }
17
18 if (guild.AllianceId?.toString() === allianceId) {
19 const alliance = await Alliance.findById(allianceId);
20 if (alliance) {
21 res.json({ AllianceVault: getAllianceVault(alliance) });
22 return;
23 }
24 }
25
26 res.end();
27 };
Modified src/controllers/api/guildTechController.ts +25 -21
@@ -13,7 +13,7 @@ import {
13 13 setGuildTechLogState
14 14 } from "../../services/guildService.ts";
15 15 import { ExportDojoRecipes, ExportRailjackWeapons } from "warframe-public-export-plus";
16 import { getAccountIdForRequest } from "../../services/loginService.ts";
16 import { getAccountForRequest } from "../../services/loginService.ts";
17 17 import {
18 18 addCrewShipWeaponSkin,
19 19 addEquipment,
@@ -31,12 +31,13 @@ import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
31 31 import type { ITechProjectClient } from "../../types/guildTypes.ts";
32 32 import { GuildPermission } from "../../types/guildTypes.ts";
33 33 import { GuildMember } from "../../models/guildModel.ts";
34 import { toMongoDate, toOid } from "../../helpers/inventoryHelpers.ts";
34 import { toMongoDate, toMongoDate2, toOid } from "../../helpers/inventoryHelpers.ts";
35 35 import { logger } from "../../utils/logger.ts";
36 36 import type { TInventoryDatabaseDocument } from "../../models/inventoryModels/inventoryModel.ts";
37 37
38 38 export const guildTechController: RequestHandler = async (req, res) => {
39 const accountId = await getAccountIdForRequest(req);
39 const account = await getAccountForRequest(req);
40 const accountId = account._id.toString();
40 41 const inventory = await getInventory(accountId);
41 42 const data = JSON.parse(String(req.body)) as TGuildTechRequest;
42 43 if (data.Action == "Sync") {
@@ -52,7 +53,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
52 53 State: project.State
53 54 };
54 55 if (project.CompletionDate) {
55 techProject.CompletionDate = toMongoDate(project.CompletionDate);
56 techProject.CompletionDate = toMongoDate2(project.CompletionDate, account.BuildLabel);
56 57 if (
57 58 Date.now() >= project.CompletionDate.getTime() &&
58 59 setGuildTechLogState(guild, project.ItemType, 4, project.CompletionDate)
@@ -69,19 +70,20 @@ export const guildTechController: RequestHandler = async (req, res) => {
69 70 }
70 71 res.json({ TechProjects: techProjects });
71 72 } else if (data.Action == "Start") {
72 if (data.Mode == "Guild") {
73 if (data.Mode != "Personal") {
73 74 const guild = await getGuildForRequestEx(req, inventory);
74 75 if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
75 76 res.status(400).send("-1").end();
76 77 return;
77 78 }
78 const recipe = ExportDojoRecipes.research[data.RecipeType];
79 const recipeType: string = (data.RecipeType || data.ResearchId)!;
80 const recipe = ExportDojoRecipes.research[recipeType];
79 81 guild.TechProjects ??= [];
80 if (!guild.TechProjects.find(x => x.ItemType == data.RecipeType)) {
82 if (!guild.TechProjects.find(x => x.ItemType == recipeType)) {
81 83 const techProject =
82 84 guild.TechProjects[
83 85 guild.TechProjects.push({
84 ItemType: data.RecipeType,
86 ItemType: recipeType,
85 87 ReqCredits: guild.noDojoResearchCosts ? 0 : scaleRequiredCount(guild.Tier, recipe.price),
86 88 ReqItems: recipe.ingredients.map(x => ({
87 89 ItemType: x.ItemType,
@@ -94,15 +96,15 @@ export const guildTechController: RequestHandler = async (req, res) => {
94 96 if (guild.noDojoResearchCosts) {
95 97 processFundedGuildTechProject(guild, techProject, recipe);
96 98 } else {
97 if (data.RecipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") {
98 guild.ActiveDojoColorResearch = data.RecipeType;
99 if (recipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") {
100 guild.ActiveDojoColorResearch = recipeType;
99 101 }
100 102 }
101 103 }
102 104 await guild.save();
103 105 res.end();
104 106 } else {
105 const recipe = ExportDojoRecipes.research[data.RecipeType];
107 const recipe = ExportDojoRecipes.research[data.RecipeType!];
106 108 if (data.TechProductCategory) {
107 109 if (
108 110 data.TechProductCategory != "CrewShipWeapons" &&
@@ -183,8 +185,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
183 185 { accountId, guildId: guild._id },
184 186 "RegularCreditsContributed MiscItemsContributed"
185 187 ))!;
186
187 const techProject = guild.TechProjects!.find(x => x.ItemType == data.RecipeType)!;
188 const recipeType = data.RecipeType || data.ResearchId;
189 const techProject = guild.TechProjects!.find(x => x.ItemType == recipeType)!;
188 190
189 191 if (data.VaultCredits) {
190 192 if (data.VaultCredits > techProject.ReqCredits) {
@@ -248,7 +250,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
248 250 }
249 251 } else if (data.Action.split(",")[0] == "Buy") {
250 252 const purchase = data as IGuildTechBuyRequest;
251 if (purchase.Mode == "Guild") {
253 if (purchase.Mode != "Personal") {
254 const recipeType: string = (purchase.RecipeType || purchase.ResearchId)!;
252 255 const guild = await getGuildForRequestEx(req, inventory);
253 256 if (
254 257 !hasAccessToDojo(inventory) ||
@@ -257,17 +260,17 @@ export const guildTechController: RequestHandler = async (req, res) => {
257 260 res.status(400).send("-1").end();
258 261 return;
259 262 }
260 const quantity = parseInt(data.Action.split(",")[1]);
263 const quantity = parseInt(data.Action.split(",")[1]) || 1;
261 264 const recipeChanges = [
262 265 {
263 ItemType: purchase.RecipeType,
266 ItemType: recipeType,
264 267 ItemCount: quantity
265 268 }
266 269 ];
267 270 addRecipes(inventory, recipeChanges);
268 271 const currencyChanges = updateCurrency(
269 272 inventory,
270 ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
273 ExportDojoRecipes.research[recipeType].replicatePrice,
271 274 false
272 275 );
273 276 await inventory.save();
@@ -291,7 +294,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
291 294 res.status(400).send("-1").end();
292 295 return;
293 296 }
294 const recipe = ExportDojoRecipes.fabrications[data.RecipeType];
297 const recipe = ExportDojoRecipes.fabrications[data.RecipeType!];
295 298 const inventoryChanges: IInventoryChanges = updateCurrency(inventory, recipe.price, false);
296 299 inventoryChanges.MiscItems = recipe.ingredients.map(x => ({
297 300 ItemType: x.ItemType,
@@ -322,7 +325,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
322 325 }
323 326 const project = guild.TechProjects!.find(x => x.ItemType == data.RecipeType)!;
324 327 project.State = 0;
325 guild.ActiveDojoColorResearch = data.RecipeType;
328 guild.ActiveDojoColorResearch = data.RecipeType!;
326 329 await guild.save();
327 330 res.end();
328 331 } else if (data.Action == "Cancel" && data.CategoryItemId) {
@@ -396,7 +399,8 @@ type TGuildTechRequest =
396 399 interface IGuildTechBasicRequest {
397 400 Action: "Start" | "Fabricate" | "Pause" | "Unpause" | "Cancel" | "Rush" | "InstantFinish";
398 401 Mode: "Guild" | "Personal";
399 RecipeType: string;
402 ResearchId?: string; // U18.0.6 uses that instead RecipeType
403 RecipeType?: string;
400 404 TechProductCategory?: string;
401 405 CategoryItemId?: string;
402 406 }
@@ -408,7 +412,7 @@ interface IGuildTechBuyRequest extends Omit<IGuildTechBasicRequest, "Action"> {
408 412 interface IGuildTechContributeRequest {
409 413 Action: "Contribute";
410 414 ResearchId: string;
411 RecipeType: string;
415 RecipeType?: string;
412 416 RegularCredits: number;
413 417 MiscItems: IMiscItem[];
414 418 VaultCredits: number;
Modified src/models/guildModel.ts +1 -0
@@ -229,6 +229,7 @@ const guildSchema = new Schema<IGuildDatabase>(
229 229 VaultShipDecorations: { type: [typeCountSchema], default: undefined },
230 230 VaultFusionTreasures: { type: [fusionTreasuresSchema], default: undefined },
231 231 VaultDecoRecipes: { type: [typeCountSchema], default: undefined },
232 VaultRecipes: { type: [typeCountSchema], default: undefined },
232 233 MaxBattlePayReserve: Number,
233 234 MaxMissionBattlePay: Number,
234 235 MinMissionBattlePay: Number,
Modified src/routes/api.ts +3 -1
@@ -79,6 +79,7 @@ import { getPastWeeklyChallengesController } from "../controllers/api/getPastWee
79 79 import { getProfileViewingDataPostController } from "../controllers/dynamic/getProfileViewingDataController.ts";
80 80 import { getRecentPlayersController } from "../controllers/api/getRecentPlayersController.ts";
81 81 import { getShipController } from "../controllers/api/getShipController.ts";
82 import { getVaultController } from "../controllers/api/getVaultController.ts";
82 83 import { getVendorInfoController } from "../controllers/api/getVendorInfoController.ts";
83 84 import { getVoidProjectionRewardsController } from "../controllers/api/getVoidProjectionRewardsController.ts";
84 85 import { giftingController } from "../controllers/api/giftingController.ts";
@@ -223,9 +224,10 @@ apiRouter.get("/getGuildLog.php", getGuildLogController);
223 224 apiRouter.get("/getIgnoredUsers.php", getIgnoredUsersController);
224 225 apiRouter.get("/getMessages.php", inboxController); // unsure if this is correct, but needed for U17
225 226 apiRouter.get("/getNewRewardSeed.php", getNewRewardSeedController);
226 apiRouter.get("/getPastWeeklyChallenges.php", getPastWeeklyChallengesController)
227 apiRouter.get("/getPastWeeklyChallenges.php", getPastWeeklyChallengesController);
227 228 apiRouter.get("/getShip.php", getShipController);
228 229 apiRouter.get("/getShipDecos.php", (_req, res) => { res.end(); }); // needed to log in on U22.8
230 apiRouter.get("/getVault.php", getVaultController);
229 231 apiRouter.get("/getVendorInfo.php", getVendorInfoController);
230 232 apiRouter.get("/giveStartingGear.php", giveStartingGearGetController);
231 233 apiRouter.get("/inbox.php", inboxController);
Modified src/services/guildService.ts +14 -3
@@ -153,6 +153,7 @@ export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
153 153 ShipDecorations: guild.VaultShipDecorations,
154 154 FusionTreasures: guild.VaultFusionTreasures,
155 155 DecoRecipes: guild.VaultDecoRecipes,
156 Recipes: guild.VaultRecipes, // Solar Rail
156 157
157 158 MaxBattlePayReserve: guild.MaxBattlePayReserve,
158 159 MaxMissionBattlePay: guild.MaxMissionBattlePay,
@@ -160,6 +161,12 @@ export const getGuildVault = (guild: TGuildDatabaseDocument): IGuildVault => {
160 161 };
161 162 };
162 163
164 export const getAllianceVault = (alliance: IAllianceDatabase): IGuildVault => {
165 return {
166 DojoRefundRegularCredits: alliance.VaultRegularCredits
167 };
168 };
169
163 170 export const getDojoClient = async (
164 171 guild: TGuildDatabaseDocument,
165 172 status: number,
@@ -621,6 +628,12 @@ export const processCompletedGuildTechProject = (guild: TGuildDatabaseDocument,
621 628 ItemType: type,
622 629 ItemCount: 1
623 630 });
631 } else if (type == "/Lotus/Types/Game/SolarRails/BasicSolarRailBlueprint") {
632 guild.VaultRecipes ??= [];
633 guild.VaultRecipes.push({
634 ItemType: type,
635 ItemCount: 1
636 });
624 637 }
625 638 };
626 639
@@ -856,9 +869,7 @@ export const getAllianceClient = async (
856 869 MOTD: alliance.MOTD,
857 870 LongMOTD: alliance.LongMOTD,
858 871 Clans: clans,
859 AllianceVault: {
860 DojoRefundRegularCredits: alliance.VaultRegularCredits
861 }
872 AllianceVault: getAllianceVault(alliance)
862 873 };
863 874 };
864 875
Modified src/types/guildTypes.ts +11 -2
@@ -1,5 +1,11 @@
1 1 import type { Types } from "mongoose";
2 import type { IOid, IMongoDate, IOidWithLegacySupport, ITypeCount } from "./commonTypes.ts";
2 import type {
3 IOid,
4 IMongoDate,
5 IOidWithLegacySupport,
6 ITypeCount,
7 IMongoDateWithLegacySupport
8 } from "./commonTypes.ts";
3 9 import type {
4 10 IFusionTreasure,
5 11 IMiscItem,
@@ -65,6 +71,7 @@ export interface IGuildDatabase extends IGuildCheats {
65 71 VaultShipDecorations?: ITypeCount[];
66 72 VaultFusionTreasures?: IFusionTreasure[];
67 73 VaultDecoRecipes?: ITypeCount[];
74 VaultRecipes?: ITypeCount[];
68 75
69 76 MaxBattlePayReserve?: number;
70 77 MaxMissionBattlePay?: number;
@@ -148,10 +155,12 @@ export interface IGuildVault {
148 155 ShipDecorations?: ITypeCount[];
149 156 FusionTreasures?: IFusionTreasure[];
150 157 DecoRecipes?: ITypeCount[]; // Event Trophies
158 Recipes?: ITypeCount[]; // Solar Rail
151 159
152 160 MaxBattlePayReserve?: number;
153 161 MaxMissionBattlePay?: number;
154 162 MinMissionBattlePay?: number;
163 // InventoryItems?: Record<"SolarRails", ITypeCount[]>;
155 164 }
156 165
157 166 export interface IDojoClient {
@@ -256,7 +265,7 @@ export interface ITechProjectClient {
256 265 ReqCredits: number;
257 266 ReqItems: IMiscItem[];
258 267 State: number; // 0 = pending, 1 = complete
259 CompletionDate?: IMongoDate;
268 CompletionDate?: IMongoDateWithLegacySupport;
260 269 }
261 270
262 271 export interface ITechProjectDatabase extends Omit<ITechProjectClient, "CompletionDate"> {