返回提交历史
Modified
src/controllers/api/abortDojoComponentController.ts
+12
-4
Modified
src/controllers/api/contributeToDojoComponentController.ts
+62
-27
Added
src/controllers/api/destroyDojoDecoController.ts
+19
-0
Modified
src/controllers/api/dojoComponentRushController.ts
+28
-14
Modified
src/controllers/api/getGuildDojoController.ts
+2
-1
Added
src/controllers/api/placeDecoInComponentController.ts
+43
-0
Modified
src/controllers/api/queueDojoComponentDestructionController.ts
+4
-11
Modified
src/controllers/api/startDojoRecipeController.ts
+2
-1
Modified
src/models/guildModel.ts
+16
-2
Modified
src/routes/api.ts
+4
-0
Modified
src/services/guildService.ts
+42
-3
Modified
src/types/guildTypes.ts
+26
-5
XFEstudio/SpaceNinjaServer
feat: dojo decorations (#1079)
Closes #525 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1079
c4ab496a
代码差异
12 个文件
+260
-68
@@ -1,4 +1,4 @@
1
import { getDojoClient, getGuildForRequestEx } from "@/src/services/guildService";
1
import { getDojoClient, getGuildForRequestEx, removeDojoDeco, removeDojoRoom } from "@/src/services/guildService";
2
2
import { getInventory } from "@/src/services/inventoryService";
3
3
import { getAccountIdForRequest } from "@/src/services/loginService";
4
4
import { RequestHandler } from "express";
@@ -8,12 +8,20 @@ export const abortDojoComponentController: RequestHandler = async (req, res) =>
8
8
const inventory = await getInventory(accountId);
9
9
const guild = await getGuildForRequestEx(req, inventory);
10
10
const request = JSON.parse(String(req.body)) as IAbortDojoComponentRequest;
11
11
12
// TODO: Move already-contributed credits & items to the clan vault
12
guild.DojoComponents.pull({ _id: request.ComponentId });
13
if (request.DecoId) {
14
removeDojoDeco(guild, request.ComponentId, request.DecoId);
15
} else {
16
removeDojoRoom(guild, request.ComponentId);
17
}
18
13
19
await guild.save();
14
res.json(getDojoClient(guild, 0));
20
res.json(getDojoClient(guild, 0, request.ComponentId));
15
21
};
16
22
17
export interface IAbortDojoComponentRequest {
23
interface IAbortDojoComponentRequest {
24
DecoType?: string;
18
25
ComponentId: string;
26
DecoId?: string;
19
27
}
@@ -1,10 +1,26 @@
1
import { TGuildDatabaseDocument } from "@/src/models/guildModel";
2
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
1
3
import { getDojoClient, getGuildForRequestEx, scaleRequiredCount } from "@/src/services/guildService";
2
4
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
3
5
import { getAccountIdForRequest } from "@/src/services/loginService";
6
import { IDojoContributable } from "@/src/types/guildTypes";
4
7
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
5
8
import { IInventoryChanges } from "@/src/types/purchaseTypes";
6
9
import { RequestHandler } from "express";
7
import { ExportDojoRecipes } from "warframe-public-export-plus";
10
import { ExportDojoRecipes, IDojoRecipe } from "warframe-public-export-plus";
11
12
interface IContributeToDojoComponentRequest {
13
ComponentId: string;
14
DecoId?: string;
15
DecoType?: string;
16
IngredientContributions: {
17
ItemType: string;
18
ItemCount: number;
19
}[];
20
RegularCredits: number;
21
VaultIngredientContributions: [];
22
VaultCredits: number;
23
}
8
24
9
25
export const contributeToDojoComponentController: RequestHandler = async (req, res) => {
10
26
const accountId = await getAccountIdForRequest(req);
@@ -13,21 +29,54 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r
13
29
// Any clan member should have permission to contribute although notably permission is denied if they have not crafted the dojo key and were simply invited in.
14
30
const request = JSON.parse(String(req.body)) as IContributeToDojoComponentRequest;
15
31
const component = guild.DojoComponents.id(request.ComponentId)!;
16
const componentMeta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
17
32
33
const inventoryChanges: IInventoryChanges = {};
34
if (!component.CompletionTime) {
35
// Room is in "Collecting Materials" state
36
if (request.DecoId) {
37
throw new Error("attempt to contribute to a deco in an unfinished room?!");
38
}
39
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
40
await processContribution(guild, request, inventory, inventoryChanges, meta, component);
41
} else {
42
// Room is past "Collecting Materials"
43
if (request.DecoId) {
44
const deco = component.Decos!.find(x => x._id.equals(request.DecoId))!;
45
const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type)!;
46
await processContribution(guild, request, inventory, inventoryChanges, meta, deco);
47
}
48
}
49
50
await guild.save();
51
await inventory.save();
52
res.json({
53
...getDojoClient(guild, 0, component._id),
54
InventoryChanges: inventoryChanges
55
});
56
};
57
58
const processContribution = async (
59
guild: TGuildDatabaseDocument,
60
request: IContributeToDojoComponentRequest,
61
inventory: TInventoryDatabaseDocument,
62
inventoryChanges: IInventoryChanges,
63
meta: IDojoRecipe,
64
component: IDojoContributable
65
): Promise<void> => {
18
66
component.RegularCredits ??= 0;
19
if (component.RegularCredits + request.RegularCredits > scaleRequiredCount(componentMeta.price)) {
20
request.RegularCredits = scaleRequiredCount(componentMeta.price) - component.RegularCredits;
67
if (component.RegularCredits + request.RegularCredits > scaleRequiredCount(meta.price)) {
68
request.RegularCredits = scaleRequiredCount(meta.price) - component.RegularCredits;
21
69
}
22
70
component.RegularCredits += request.RegularCredits;
23
const inventoryChanges: IInventoryChanges = updateCurrency(inventory, request.RegularCredits, false);
71
inventoryChanges.RegularCredits = -request.RegularCredits;
72
updateCurrency(inventory, request.RegularCredits, false);
24
73
25
74
component.MiscItems ??= [];
26
75
const miscItemChanges: IMiscItem[] = [];
27
76
for (const ingredientContribution of request.IngredientContributions) {
28
77
const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredientContribution.ItemType);
29
78
if (componentMiscItem) {
30
const ingredientMeta = componentMeta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
79
const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
31
80
if (
32
81
componentMiscItem.ItemCount + ingredientContribution.ItemCount >
33
82
scaleRequiredCount(ingredientMeta.ItemCount)
@@ -47,9 +96,9 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r
47
96
addMiscItems(inventory, miscItemChanges);
48
97
inventoryChanges.MiscItems = miscItemChanges;
49
98
50
if (component.RegularCredits >= scaleRequiredCount(componentMeta.price)) {
99
if (component.RegularCredits >= scaleRequiredCount(meta.price)) {
51
100
let fullyFunded = true;
52
for (const ingredient of componentMeta.ingredients) {
101
for (const ingredient of meta.ingredients) {
53
102
const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredient.ItemType);
54
103
if (!componentMiscItem || componentMiscItem.ItemCount < scaleRequiredCount(ingredient.ItemCount)) {
55
104
fullyFunded = false;
@@ -57,27 +106,13 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r
57
106
}
58
107
}
59
108
if (fullyFunded) {
109
if (request.IngredientContributions.length) {
110
// We've already updated subpaths of MiscItems, we need to allow MongoDB to save this before we remove MiscItems.
111
await guild.save();
112
}
60
113
component.RegularCredits = undefined;
61
114
component.MiscItems = undefined;
62
component.CompletionTime = new Date(Date.now() + componentMeta.time * 1000);
115
component.CompletionTime = new Date(Date.now() + meta.time * 1000);
63
116
}
64
117
}
65
66
await guild.save();
67
await inventory.save();
68
res.json({
69
...getDojoClient(guild, 0, component._id),
70
InventoryChanges: inventoryChanges
71
});
72
118
};
73
74
export interface IContributeToDojoComponentRequest {
75
ComponentId: string;
76
IngredientContributions: {
77
ItemType: string;
78
ItemCount: number;
79
}[];
80
RegularCredits: number;
81
VaultIngredientContributions: [];
82
VaultCredits: number;
83
}
@@ -0,0 +1,19 @@
1
import { getDojoClient, getGuildForRequest, removeDojoDeco } from "@/src/services/guildService";
2
import { RequestHandler } from "express";
3
4
export const destroyDojoDecoController: RequestHandler = async (req, res) => {
5
const guild = await getGuildForRequest(req);
6
const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest;
7
8
removeDojoDeco(guild, request.ComponentId, request.DecoId);
9
// TODO: The client says this is supposed to refund the resources to the clan vault, so we should probably do that.
10
11
await guild.save();
12
res.json(getDojoClient(guild, 0, request.ComponentId));
13
};
14
15
interface IDestroyDojoDecoRequest {
16
DecoType: string;
17
ComponentId: string;
18
DecoId: string;
19
}
@@ -1,8 +1,18 @@
1
1
import { getDojoClient, getGuildForRequestEx, scaleRequiredCount } from "@/src/services/guildService";
2
2
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
3
3
import { getAccountIdForRequest } from "@/src/services/loginService";
4
import { IDojoContributable } from "@/src/types/guildTypes";
4
5
import { RequestHandler } from "express";
5
import { ExportDojoRecipes } from "warframe-public-export-plus";
6
import { ExportDojoRecipes, IDojoRecipe } from "warframe-public-export-plus";
7
8
interface IDojoComponentRushRequest {
9
DecoType?: string;
10
DecoId?: string;
11
ComponentId: string;
12
Amount: number;
13
VaultAmount: number;
14
AllianceVaultAmount: number;
15
}
6
16
7
17
export const dojoComponentRushController: RequestHandler = async (req, res) => {
8
18
const accountId = await getAccountIdForRequest(req);
@@ -10,14 +20,16 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
10
20
const guild = await getGuildForRequestEx(req, inventory);
11
21
const request = JSON.parse(String(req.body)) as IDojoComponentRushRequest;
12
22
const component = guild.DojoComponents.id(request.ComponentId)!;
13
const componentMeta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
14
23
15
const fullPlatinumCost = scaleRequiredCount(componentMeta.skipTimePrice);
16
const fullDurationSeconds = componentMeta.time;
17
const secondsPerPlatinum = fullDurationSeconds / fullPlatinumCost;
18
component.CompletionTime = new Date(
19
component.CompletionTime!.getTime() - secondsPerPlatinum * request.Amount * 1000
20
);
24
if (request.DecoId) {
25
const deco = component.Decos!.find(x => x._id.equals(request.DecoId))!;
26
const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type)!;
27
processContribution(deco, meta, request.Amount);
28
} else {
29
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
30
processContribution(component, meta, request.Amount);
31
}
32
21
33
const inventoryChanges = updateCurrency(inventory, request.Amount, true);
22
34
23
35
await guild.save();
@@ -28,9 +40,11 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
28
40
});
29
41
};
30
42
31
interface IDojoComponentRushRequest {
32
ComponentId: string;
33
Amount: number;
34
VaultAmount: number;
35
AllianceVaultAmount: number;
36
}
43
const processContribution = (component: IDojoContributable, meta: IDojoRecipe, platinumDonated: number): void => {
44
const fullPlatinumCost = scaleRequiredCount(meta.skipTimePrice);
45
const fullDurationSeconds = meta.time;
46
const secondsPerPlatinum = fullDurationSeconds / fullPlatinumCost;
47
component.CompletionTime = new Date(
48
component.CompletionTime!.getTime() - secondsPerPlatinum * platinumDonated * 1000
49
);
50
};
@@ -18,7 +18,8 @@ export const getGuildDojoController: RequestHandler = async (req, res) => {
18
18
_id: new Types.ObjectId(),
19
19
pf: "/Lotus/Levels/ClanDojo/DojoHall.level",
20
20
ppf: "",
21
CompletionTime: new Date(Date.now())
21
CompletionTime: new Date(Date.now()),
22
DecoCapacity: 600
22
23
});
23
24
await guild.save();
24
25
}
@@ -0,0 +1,43 @@
1
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
2
import { RequestHandler } from "express";
3
import { Types } from "mongoose";
4
import { ExportDojoRecipes } from "warframe-public-export-plus";
5
6
export const placeDecoInComponentController: RequestHandler = async (req, res) => {
7
const guild = await getGuildForRequest(req);
8
const request = JSON.parse(String(req.body)) as IPlaceDecoInComponentRequest;
9
// At this point, we know that a member of the guild is making this request. Assuming they are allowed to place decorations.
10
const component = guild.DojoComponents.id(request.ComponentId)!;
11
12
if (component.DecoCapacity === undefined) {
13
component.DecoCapacity = Object.values(ExportDojoRecipes.rooms).find(
14
x => x.resultType == component.pf
15
)!.decoCapacity;
16
}
17
18
component.Decos ??= [];
19
component.Decos.push({
20
_id: new Types.ObjectId(),
21
Type: request.Type,
22
Pos: request.Pos,
23
Rot: request.Rot,
24
Name: request.Name
25
});
26
27
const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == request.Type);
28
if (meta && meta.capacityCost) {
29
component.DecoCapacity -= meta.capacityCost;
30
}
31
32
await guild.save();
33
res.json(getDojoClient(guild, 0, component._id));
34
};
35
36
interface IPlaceDecoInComponentRequest {
37
ComponentId: string;
38
Revision: number;
39
Type: string;
40
Pos: number[];
41
Rot: number[];
42
Name?: string;
43
}
@@ -1,19 +1,12 @@
1
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
1
import { getDojoClient, getGuildForRequest, removeDojoRoom } from "@/src/services/guildService";
2
2
import { RequestHandler } from "express";
3
import { ExportDojoRecipes } from "warframe-public-export-plus";
4
3
5
4
export const queueDojoComponentDestructionController: RequestHandler = async (req, res) => {
6
5
const guild = await getGuildForRequest(req);
7
6
const componentId = req.query.componentId as string;
8
const component = guild.DojoComponents.splice(
9
guild.DojoComponents.findIndex(x => x._id.toString() === componentId),
10
1
11
)[0];
12
const room = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf);
13
if (room) {
14
guild.DojoCapacity -= room.capacity;
15
guild.DojoEnergy -= room.energy;
16
}
7
8
removeDojoRoom(guild, componentId);
9
17
10
await guild.save();
18
11
res.json(getDojoClient(guild, 1));
19
12
};
@@ -29,7 +29,8 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
29
29
ppf: request.PlacedComponent.ppf,
30
30
pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
31
31
op: request.PlacedComponent.op,
32
pp: request.PlacedComponent.pp
32
pp: request.PlacedComponent.pp,
33
DecoCapacity: room?.decoCapacity
33
34
}) - 1
34
35
];
35
36
if (config.noDojoRoomBuildStage) {
@@ -2,12 +2,23 @@ import {
2
2
IGuildDatabase,
3
3
IDojoComponentDatabase,
4
4
ITechProjectDatabase,
5
ITechProjectClient
5
ITechProjectClient,
6
IDojoDecoDatabase
6
7
} from "@/src/types/guildTypes";
7
8
import { Document, Model, model, Schema, Types } from "mongoose";
8
9
import { typeCountSchema } from "./inventoryModels/inventoryModel";
9
10
import { toMongoDate } from "../helpers/inventoryHelpers";
10
11
12
const dojoDecoSchema = new Schema<IDojoDecoDatabase>({
13
Type: String,
14
Pos: [Number],
15
Rot: [Number],
16
Name: String,
17
RegularCredits: Number,
18
MiscItems: { type: [typeCountSchema], default: undefined },
19
CompletionTime: Date
20
});
21
11
22
const dojoComponentSchema = new Schema<IDojoComponentDatabase>({
12
23
pf: { type: String, required: true },
13
24
ppf: String,
@@ -18,7 +29,10 @@ const dojoComponentSchema = new Schema<IDojoComponentDatabase>({
18
29
Message: String,
19
30
RegularCredits: Number,
20
31
MiscItems: { type: [typeCountSchema], default: undefined },
21
CompletionTime: Date
32
CompletionTime: Date,
33
DestructionTime: Date,
34
Decos: [dojoDecoSchema],
35
DecoCapacity: Number
22
36
});
23
37
24
38
const techProjectSchema = new Schema<ITechProjectDatabase>(
@@ -16,6 +16,7 @@ import { contributeToDojoComponentController } from "@/src/controllers/api/contr
16
16
import { createGuildController } from "@/src/controllers/api/createGuildController";
17
17
import { creditsController } from "@/src/controllers/api/creditsController";
18
18
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
19
import { destroyDojoDecoController } from "@/src/controllers/api/destroyDojoDecoController";
19
20
import { dojoComponentRushController } from "@/src/controllers/api/dojoComponentRushController";
20
21
import { dojoController } from "@/src/controllers/api/dojoController";
21
22
import { dronesController } from "@/src/controllers/api/dronesController";
@@ -59,6 +60,7 @@ import { missionInventoryUpdateController } from "@/src/controllers/api/missionI
59
60
import { modularWeaponCraftingController } from "@/src/controllers/api/modularWeaponCraftingController";
60
61
import { modularWeaponSaleController } from "@/src/controllers/api/modularWeaponSaleController";
61
62
import { nameWeaponController } from "@/src/controllers/api/nameWeaponController";
63
import { placeDecoInComponentController } from "@/src/controllers/api/placeDecoInComponentController";
62
64
import { playerSkillsController } from "@/src/controllers/api/playerSkillsController";
63
65
import { projectionManagerController } from "@/src/controllers/api/projectionManagerController";
64
66
import { purchaseController } from "@/src/controllers/api/purchaseController";
@@ -150,6 +152,7 @@ apiRouter.post("/clearDialogueHistory.php", clearDialogueHistoryController);
150
152
apiRouter.post("/completeRandomModChallenge.php", completeRandomModChallengeController);
151
153
apiRouter.post("/contributeToDojoComponent.php", contributeToDojoComponentController);
152
154
apiRouter.post("/createGuild.php", createGuildController);
155
apiRouter.post("/destroyDojoDeco.php", destroyDojoDecoController);
153
156
apiRouter.post("/dojoComponentRush.php", dojoComponentRushController);
154
157
apiRouter.post("/drones.php", dronesController);
155
158
apiRouter.post("/endlessXp.php", endlessXpController);
@@ -175,6 +178,7 @@ apiRouter.post("/login.php", loginController);
175
178
apiRouter.post("/missionInventoryUpdate.php", missionInventoryUpdateController);
176
179
apiRouter.post("/modularWeaponCrafting.php", modularWeaponCraftingController);
177
180
apiRouter.post("/nameWeapon.php", nameWeaponController);
181
apiRouter.post("/placeDecoInComponent.php", placeDecoInComponentController);
178
182
apiRouter.post("/playerSkills.php", playerSkillsController);
179
183
apiRouter.post("/projectionManager.php", projectionManagerController);
180
184
apiRouter.post("/purchase.php", purchaseController);
@@ -6,6 +6,7 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
6
6
import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes";
7
7
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
8
8
import { Types } from "mongoose";
9
import { ExportDojoRecipes } from "warframe-public-export-plus";
9
10
10
11
export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
11
12
const accountId = await getAccountIdForRequest(req);
@@ -31,7 +32,7 @@ export const getGuildForRequestEx = async (
31
32
export const getDojoClient = (
32
33
guild: TGuildDatabaseDocument,
33
34
status: number,
34
componentId: Types.ObjectId | undefined = undefined
35
componentId: Types.ObjectId | string | undefined = undefined
35
36
): IDojoClient => {
36
37
const dojo: IDojoClient = {
37
38
_id: { $oid: guild._id.toString() },
@@ -46,14 +47,14 @@ export const getDojoClient = (
46
47
DojoComponents: []
47
48
};
48
49
guild.DojoComponents.forEach(dojoComponent => {
49
if (!componentId || componentId == dojoComponent._id) {
50
if (!componentId || dojoComponent._id.equals(componentId)) {
50
51
const clientComponent: IDojoComponentClient = {
51
52
id: toOid(dojoComponent._id),
52
53
pf: dojoComponent.pf,
53
54
ppf: dojoComponent.ppf,
54
55
Name: dojoComponent.Name,
55
56
Message: dojoComponent.Message,
56
DecoCapacity: 600
57
DecoCapacity: dojoComponent.DecoCapacity ?? 600
57
58
};
58
59
if (dojoComponent.pi) {
59
60
clientComponent.pi = toOid(dojoComponent.pi);
@@ -66,6 +67,20 @@ export const getDojoClient = (
66
67
clientComponent.RegularCredits = dojoComponent.RegularCredits;
67
68
clientComponent.MiscItems = dojoComponent.MiscItems;
68
69
}
70
if (dojoComponent.Decos) {
71
clientComponent.Decos = [];
72
for (const deco of dojoComponent.Decos) {
73
clientComponent.Decos.push({
74
id: toOid(deco._id),
75
Type: deco.Type,
76
Pos: deco.Pos,
77
Rot: deco.Rot,
78
CompletionTime: deco.CompletionTime ? toMongoDate(deco.CompletionTime) : undefined,
79
RegularCredits: deco.RegularCredits,
80
MiscItems: deco.MiscItems
81
});
82
}
83
}
69
84
dojo.DojoComponents.push(clientComponent);
70
85
}
71
86
});
@@ -76,3 +91,27 @@ export const scaleRequiredCount = (count: number): number => {
76
91
// The recipes in the export are for Moon clans. For now we'll just assume we only have Ghost clans.
77
92
return Math.max(1, Math.trunc(count / 100));
78
93
};
94
95
export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: string): void => {
96
const component = guild.DojoComponents.splice(
97
guild.DojoComponents.findIndex(x => x._id.equals(componentId)),
98
1
99
)[0];
100
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf);
101
if (meta) {
102
guild.DojoCapacity -= meta.capacity;
103
guild.DojoEnergy -= meta.energy;
104
}
105
};
106
107
export const removeDojoDeco = (guild: TGuildDatabaseDocument, componentId: string, decoId: string): void => {
108
const component = guild.DojoComponents.id(componentId)!;
109
const deco = component.Decos!.splice(
110
component.Decos!.findIndex(x => x._id.equals(decoId)),
111
1
112
)[0];
113
const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type);
114
if (meta && meta.capacityCost) {
115
component.DecoCapacity! += meta.capacityCost;
116
}
117
};
@@ -41,18 +41,33 @@ export interface IDojoComponentClient {
41
41
CompletionTime?: IMongoDate;
42
42
RushPlatinum?: number;
43
43
DestructionTime?: IMongoDate;
44
Decos?: IDojoDecoClient[];
44
45
DecoCapacity?: number;
45
46
}
46
47
47
48
export interface IDojoComponentDatabase
48
extends Omit<
49
IDojoComponentClient,
50
"id" | "pi" | "CompletionTime" | "RushPlatinum" | "DestructionTime" | "DecoCapacity"
51
> {
49
extends Omit<IDojoComponentClient, "id" | "pi" | "CompletionTime" | "RushPlatinum" | "DestructionTime" | "Decos"> {
52
50
_id: Types.ObjectId;
53
51
pi?: Types.ObjectId;
54
52
CompletionTime?: Date;
55
//DestructionTime?: Date;
53
DestructionTime?: Date;
54
Decos?: IDojoDecoDatabase[];
55
}
56
57
export interface IDojoDecoClient {
58
id: IOid;
59
Type: string;
60
Pos: number[];
61
Rot: number[];
62
Name?: string; // for teleporters
63
RegularCredits?: number;
64
MiscItems?: IMiscItem[];
65
CompletionTime?: IMongoDate;
66
}
67
68
export interface IDojoDecoDatabase extends Omit<IDojoDecoClient, "id" | "CompletionTime"> {
69
_id: Types.ObjectId;
70
CompletionTime?: Date;
56
71
}
57
72
58
73
export interface ITechProjectClient {
@@ -66,3 +81,9 @@ export interface ITechProjectClient {
66
81
export interface ITechProjectDatabase extends Omit<ITechProjectClient, "CompletionDate"> {
67
82
CompletionDate?: Date;
68
83
}
84
85
export interface IDojoContributable {
86
RegularCredits?: number;
87
MiscItems?: IMiscItem[];
88
CompletionTime?: Date;
89
}