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: personal decos in dojo & move dojo decos (#1451)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1451 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>

61062e43
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

10 个文件 +140 -43
Modified package-lock.json +4 -4
@@ -18,7 +18,7 @@
18 18 "morgan": "^1.10.0",
19 19 "ncp": "^2.0.0",
20 20 "typescript": ">=5.5 <5.6.0",
21 "warframe-public-export-plus": "^0.5.49",
21 "warframe-public-export-plus": "^0.5.50",
22 22 "warframe-riven-info": "^0.1.2",
23 23 "winston": "^3.17.0",
24 24 "winston-daily-rotate-file": "^5.0.0"
@@ -3789,9 +3789,9 @@
3789 3789 }
3790 3790 },
3791 3791 "node_modules/warframe-public-export-plus": {
3792 "version": "0.5.49",
3793 "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.49.tgz",
3794 "integrity": "sha512-11HA8qEMhFfl12W2qIjjk7fhas+/5G2yXbrOEb8FRZby6tWka0CyUnB6tLT+PCqBEIoU+kwhz0g7CLh3Zmy7Pw=="
3792 "version": "0.5.50",
3793 "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.50.tgz",
3794 "integrity": "sha512-KlhdY/Q5sRAIn/RhmdviKBoX3gk+Jtuen0cWnFB2zqK7eKYMDtd79bKOtTPtnK9zCNzh6gFug2wEeDVam3Bwlw=="
3795 3795 },
3796 3796 "node_modules/warframe-riven-info": {
3797 3797 "version": "0.1.2",
Modified package.json +1 -1
@@ -24,7 +24,7 @@
24 24 "morgan": "^1.10.0",
25 25 "ncp": "^2.0.0",
26 26 "typescript": ">=5.5 <5.6.0",
27 "warframe-public-export-plus": "^0.5.49",
27 "warframe-public-export-plus": "^0.5.50",
28 28 "warframe-riven-info": "^0.1.2",
29 29 "winston": "^3.17.0",
30 30 "winston-daily-rotate-file": "^5.0.0"
Modified src/controllers/api/contributeToVaultController.ts +6 -8
@@ -1,7 +1,10 @@
1 1 import { Alliance, GuildMember } from "@/src/models/guildModel";
2 2 import {
3 3 addGuildMemberMiscItemContribution,
4 addGuildMemberShipDecoContribution,
5 addVaultFusionTreasures,
4 6 addVaultMiscItems,
7 addVaultShipDecos,
5 8 getGuildForRequestEx
6 9 } from "@/src/services/guildService";
7 10 import {
@@ -51,26 +54,21 @@ export const contributeToVaultController: RequestHandler = async (req, res) => {
51 54 }
52 55 if (request.MiscItems.length) {
53 56 addVaultMiscItems(guild, request.MiscItems);
54
55 57 for (const item of request.MiscItems) {
56 58 addGuildMemberMiscItemContribution(guildMember, item);
57
58 59 addMiscItems(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]);
59 60 }
60 61 }
61 62 if (request.ShipDecorations.length) {
62 guild.VaultShipDecorations ??= [];
63 guildMember.ShipDecorationsContributed ??= [];
63 addVaultShipDecos(guild, request.ShipDecorations);
64 64 for (const item of request.ShipDecorations) {
65 guild.VaultShipDecorations.push(item);
66 guildMember.ShipDecorationsContributed.push(item);
65 addGuildMemberShipDecoContribution(guildMember, item);
67 66 addShipDecorations(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]);
68 67 }
69 68 }
70 69 if (request.FusionTreasures.length) {
71 guild.VaultFusionTreasures ??= [];
70 addVaultFusionTreasures(guild, request.FusionTreasures);
72 71 for (const item of request.FusionTreasures) {
73 guild.VaultFusionTreasures.push(item);
74 72 addFusionTreasures(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]);
75 73 }
76 74 }
Modified src/controllers/api/placeDecoInComponentController.ts +36 -17
@@ -12,7 +12,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
12 12 import { GuildPermission } from "@/src/types/guildTypes";
13 13 import { RequestHandler } from "express";
14 14 import { Types } from "mongoose";
15 import { ExportDojoRecipes } from "warframe-public-export-plus";
15 import { ExportDojoRecipes, ExportResources } from "warframe-public-export-plus";
16 16
17 17 export const placeDecoInComponentController: RequestHandler = async (req, res) => {
18 18 const accountId = await getAccountIdForRequest(req);
@@ -32,23 +32,37 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
32 32 }
33 33
34 34 component.Decos ??= [];
35 const deco =
36 component.Decos[
37 component.Decos.push({
38 _id: new Types.ObjectId(),
39 Type: request.Type,
40 Pos: request.Pos,
41 Rot: request.Rot,
42 Name: request.Name
43 }) - 1
44 ];
45
46 const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == request.Type);
47 if (meta) {
48 if (meta.capacityCost) {
49 component.DecoCapacity -= meta.capacityCost;
35 if (request.MoveId) {
36 const deco = component.Decos.find(x => x._id.equals(request.MoveId))!;
37 deco.Pos = request.Pos;
38 deco.Rot = request.Rot;
39 } else {
40 const deco =
41 component.Decos[
42 component.Decos.push({
43 _id: new Types.ObjectId(),
44 Type: request.Type,
45 Pos: request.Pos,
46 Rot: request.Rot,
47 Name: request.Name,
48 Sockets: request.Sockets
49 }) - 1
50 ];
51 const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == request.Type);
52 if (meta) {
53 if (meta.capacityCost) {
54 component.DecoCapacity -= meta.capacityCost;
55 }
56 } else {
57 const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
58 if (deco.Sockets !== undefined) {
59 guild.VaultFusionTreasures!.find(x => x.ItemType == itemType && x.Sockets == deco.Sockets)!.ItemCount -=
60 1;
61 } else {
62 guild.VaultShipDecorations!.find(x => x.ItemType == itemType)!.ItemCount -= 1;
63 }
50 64 }
51 if (meta.price == 0 && meta.ingredients.length == 0) {
65 if (!meta || (meta.price == 0 && meta.ingredients.length == 0)) {
52 66 deco.CompletionTime = new Date();
53 67 } else if (guild.AutoContributeFromVault && guild.VaultRegularCredits && guild.VaultMiscItems) {
54 68 if (guild.VaultRegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) {
@@ -94,4 +108,9 @@ interface IPlaceDecoInComponentRequest {
94 108 Pos: number[];
95 109 Rot: number[];
96 110 Name?: string;
111 Sockets?: number;
112 Scale?: number; // only provided alongside MoveId and seems to always be 1
113 MoveId?: string;
114 ShipDeco?: boolean;
115 VaultDeco?: boolean;
97 116 }
Modified src/models/guildModel.ts +4 -1
@@ -17,16 +17,19 @@ import {
17 17 } from "@/src/types/guildTypes";
18 18 import { Document, Model, model, Schema, Types } from "mongoose";
19 19 import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
20 import { pictureFrameInfoSchema } from "./personalRoomsModel";
20 21
21 22 const dojoDecoSchema = new Schema<IDojoDecoDatabase>({
22 23 Type: String,
23 24 Pos: [Number],
24 25 Rot: [Number],
25 26 Name: String,
27 Sockets: Number,
26 28 RegularCredits: Number,
27 29 MiscItems: { type: [typeCountSchema], default: undefined },
28 30 CompletionTime: Date,
29 RushPlatinum: Number
31 RushPlatinum: Number,
32 PictureFrameInfo: pictureFrameInfoSchema
30 33 });
31 34
32 35 const dojoLeaderboardEntrySchema = new Schema<IDojoLeaderboardEntry>(
Modified src/models/personalRoomsModel.ts +1 -1
@@ -12,7 +12,7 @@ import {
12 12 } from "@/src/types/shipTypes";
13 13 import { Schema, model } from "mongoose";
14 14
15 const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
15 export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
16 16 {
17 17 Image: String,
18 18 Filter: String,
Modified src/services/guildService.ts +68 -10
@@ -21,13 +21,13 @@ import {
21 21 } from "@/src/types/guildTypes";
22 22 import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
23 23 import { Types } from "mongoose";
24 import { ExportDojoRecipes, IDojoBuild, IDojoResearch } from "warframe-public-export-plus";
24 import { ExportDojoRecipes, ExportResources, IDojoBuild, IDojoResearch } from "warframe-public-export-plus";
25 25 import { logger } from "../utils/logger";
26 26 import { config } from "./configService";
27 27 import { Account } from "../models/loginModel";
28 28 import { getRandomInt } from "./rngService";
29 29 import { Inbox } from "../models/inboxModel";
30 import { ITypeCount } from "../types/inventoryTypes/inventoryTypes";
30 import { IFusionTreasure, ITypeCount } from "../types/inventoryTypes/inventoryTypes";
31 31 import { IInventoryChanges } from "../types/purchaseTypes";
32 32
33 33 export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
@@ -202,7 +202,9 @@ export const getDojoClient = async (
202 202 Type: deco.Type,
203 203 Pos: deco.Pos,
204 204 Rot: deco.Rot,
205 Name: deco.Name
205 Name: deco.Name,
206 Sockets: deco.Sockets,
207 PictureFrameInfo: deco.PictureFrameInfo
206 208 };
207 209 if (deco.CompletionTime) {
208 210 clientDeco.CompletionTime = toMongoDate(deco.CompletionTime);
@@ -285,8 +287,28 @@ export const removeDojoDeco = (
285 287 1
286 288 )[0];
287 289 const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type);
288 if (meta && meta.capacityCost) {
289 component.DecoCapacity! += meta.capacityCost;
290 if (meta) {
291 if (meta.capacityCost) {
292 component.DecoCapacity! += meta.capacityCost;
293 }
294 } else {
295 const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
296 if (deco.Sockets !== undefined) {
297 addVaultFusionTreasures(guild, [
298 {
299 ItemType: itemType,
300 ItemCount: 1,
301 Sockets: deco.Sockets
302 }
303 ]);
304 } else {
305 addVaultShipDecos(guild, [
306 {
307 ItemType: itemType,
308 ItemCount: 1
309 }
310 ]);
311 }
290 312 }
291 313 moveResourcesToVault(guild, deco);
292 314 };
@@ -311,12 +333,38 @@ export const getVaultMiscItemCount = (guild: TGuildDatabaseDocument, itemType: s
311 333
312 334 export const addVaultMiscItems = (guild: TGuildDatabaseDocument, miscItems: ITypeCount[]): void => {
313 335 guild.VaultMiscItems ??= [];
314 for (const miscItem of miscItems) {
315 const vaultMiscItem = guild.VaultMiscItems.find(x => x.ItemType == miscItem.ItemType);
316 if (vaultMiscItem) {
317 vaultMiscItem.ItemCount += miscItem.ItemCount;
336 for (const item of miscItems) {
337 const vaultItem = guild.VaultMiscItems.find(x => x.ItemType == item.ItemType);
338 if (vaultItem) {
339 vaultItem.ItemCount += item.ItemCount;
340 } else {
341 guild.VaultMiscItems.push(item);
342 }
343 }
344 };
345
346 export const addVaultShipDecos = (guild: TGuildDatabaseDocument, shipDecos: ITypeCount[]): void => {
347 guild.VaultShipDecorations ??= [];
348 for (const item of shipDecos) {
349 const vaultItem = guild.VaultShipDecorations.find(x => x.ItemType == item.ItemType);
350 if (vaultItem) {
351 vaultItem.ItemCount += item.ItemCount;
318 352 } else {
319 guild.VaultMiscItems.push(miscItem);
353 guild.VaultShipDecorations.push(item);
354 }
355 }
356 };
357
358 export const addVaultFusionTreasures = (guild: TGuildDatabaseDocument, fusionTreasures: IFusionTreasure[]): void => {
359 guild.VaultFusionTreasures ??= [];
360 for (const item of fusionTreasures) {
361 const vaultItem = guild.VaultFusionTreasures.find(
362 x => x.ItemType == item.ItemType && x.Sockets == item.Sockets
363 );
364 if (vaultItem) {
365 vaultItem.ItemCount += item.ItemCount;
366 } else {
367 guild.VaultFusionTreasures.push(item);
320 368 }
321 369 }
322 370 };
@@ -331,6 +379,16 @@ export const addGuildMemberMiscItemContribution = (guildMember: IGuildMemberData
331 379 }
332 380 };
333 381
382 export const addGuildMemberShipDecoContribution = (guildMember: IGuildMemberDatabase, item: ITypeCount): void => {
383 guildMember.ShipDecorationsContributed ??= [];
384 const shipDecoContribution = guildMember.ShipDecorationsContributed.find(x => x.ItemType == item.ItemType);
385 if (shipDecoContribution) {
386 shipDecoContribution.ItemCount += item.ItemCount;
387 } else {
388 guildMember.ShipDecorationsContributed.push(item);
389 }
390 };
391
334 392 export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument, build: IDojoBuild): void => {
335 393 if (build.guildXpValue) {
336 394 guild.ClaimedXP ??= [];
Modified src/services/shipCustomizationsService.ts +14 -0
@@ -10,6 +10,9 @@ import { logger } from "@/src/utils/logger";
10 10 import { Types } from "mongoose";
11 11 import { addShipDecorations, getInventory } from "./inventoryService";
12 12 import { config } from "./configService";
13 import { Guild } from "../models/guildModel";
14 import { hasGuildPermission } from "./guildService";
15 import { GuildPermission } from "../types/guildTypes";
13 16
14 17 export const setShipCustomizations = async (
15 18 accountId: string,
@@ -154,6 +157,17 @@ export const handleSetShipDecorations = async (
154 157 };
155 158
156 159 export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlacedDecoInfoRequest): Promise<void> => {
160 if (req.GuildId && req.ComponentId) {
161 const guild = (await Guild.findById(req.GuildId))!;
162 if (await hasGuildPermission(guild, accountId, GuildPermission.Decorator)) {
163 const component = guild.DojoComponents.id(req.ComponentId)!;
164 const deco = component.Decos!.find(x => x._id.equals(req.DecoId))!;
165 deco.PictureFrameInfo = req.PictureFrameInfo;
166 await guild.save();
167 }
168 return;
169 }
170
157 171 const personalRooms = await getPersonalRooms(accountId);
158 172
159 173 const room = personalRooms.Ship.Rooms.find(room => room.Name === req.Room);
Modified src/types/guildTypes.ts +3 -0
@@ -1,6 +1,7 @@
1 1 import { Types } from "mongoose";
2 2 import { IOid, IMongoDate } from "@/src/types/commonTypes";
3 3 import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
4 import { IPictureFrameInfo } from "./shipTypes";
4 5
5 6 export interface IGuildClient {
6 7 _id: IOid;
@@ -191,10 +192,12 @@ export interface IDojoDecoClient {
191 192 Pos: number[];
192 193 Rot: number[];
193 194 Name?: string; // for teleporters
195 Sockets?: number;
194 196 RegularCredits?: number;
195 197 MiscItems?: IMiscItem[];
196 198 CompletionTime?: IMongoDate;
197 199 RushPlatinum?: number;
200 PictureFrameInfo?: IPictureFrameInfo;
198 201 }
199 202
200 203 export interface IDojoDecoDatabase extends Omit<IDojoDecoClient, "id" | "CompletionTime"> {
Modified src/types/shipTypes.ts +3 -1
@@ -127,7 +127,9 @@ export interface ISetPlacedDecoInfoRequest {
127 127 DecoId: string;
128 128 Room: string;
129 129 PictureFrameInfo: IPictureFrameInfo;
130 BootLocation: string;
130 BootLocation?: string;
131 ComponentId?: string;
132 GuildId?: string;
131 133 }
132 134
133 135 export interface IPictureFrameInfo {