返回提交历史
Modified
package-lock.json
+4
-4
Modified
package.json
+1
-1
Modified
src/controllers/api/contributeToVaultController.ts
+6
-8
Modified
src/controllers/api/placeDecoInComponentController.ts
+36
-17
Modified
src/models/guildModel.ts
+4
-1
Modified
src/models/personalRoomsModel.ts
+1
-1
Modified
src/services/guildService.ts
+68
-10
Modified
src/services/shipCustomizationsService.ts
+14
-0
Modified
src/types/guildTypes.ts
+3
-0
Modified
src/types/shipTypes.ts
+3
-1
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
代码差异
10 个文件
+140
-43
@@ -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",
@@ -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"
@@ -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
}
@@ -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
}
@@ -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>(
@@ -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,
@@ -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 ??= [];
@@ -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);
@@ -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"> {
@@ -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 {