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: track RoomChanges in clan log (#1174)

Final part for clan log; closes #1152 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1174

0c067769
Sainan <sainan@calamity.inc>
提交于

代码差异

7 个文件 +89 -7
Modified src/controllers/api/contributeToDojoComponentController.ts +6 -1
@@ -4,7 +4,8 @@ import {
4 4 getDojoClient,
5 5 getGuildForRequestEx,
6 6 processDojoBuildMaterialsGathered,
7 scaleRequiredCount
7 scaleRequiredCount,
8 setDojoRoomLogFunded
8 9 } from "@/src/services/guildService";
9 10 import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
10 11 import { getAccountIdForRequest } from "@/src/services/loginService";
@@ -40,6 +41,10 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r
40 41 }
41 42 const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
42 43 processContribution(guild, request, inventory, inventoryChanges, meta, component);
44 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
45 if (component.CompletionTime) {
46 setDojoRoomLogFunded(guild, component);
47 }
43 48 } else {
44 49 // Room is past "Collecting Materials"
45 50 if (request.DecoId) {
Modified src/controllers/api/dojoComponentRushController.ts +5 -0
@@ -35,6 +35,11 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
35 35 } else {
36 36 const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
37 37 processContribution(component, meta, platinumDonated);
38
39 const entry = guild.RoomChanges?.find(x => x.componentId.equals(component._id));
40 if (entry) {
41 entry.dateTime = component.CompletionTime!;
42 }
38 43 }
39 44
40 45 await guild.save();
Modified src/controllers/api/getGuildLogController.ts +7 -0
@@ -18,6 +18,13 @@ export const getGuildLogController: RequestHandler = async (req, res) => {
18 18 StandingsUpdates: [],
19 19 ClassChanges: []
20 20 };
21 guild.RoomChanges?.forEach(entry => {
22 log.RoomChanges.push({
23 dateTime: toMongoDate(entry.dateTime),
24 entryType: entry.entryType,
25 details: entry.details
26 });
27 });
21 28 guild.TechChanges?.forEach(entry => {
22 29 log.TechChanges.push({
23 30 dateTime: toMongoDate(entry.dateTime),
Modified src/controllers/api/startDojoRecipeController.ts +18 -2
@@ -1,6 +1,11 @@
1 1 import { RequestHandler } from "express";
2 2 import { IDojoComponentClient } from "@/src/types/guildTypes";
3 import { getDojoClient, getGuildForRequest, processDojoBuildMaterialsGathered } from "@/src/services/guildService";
3 import {
4 getDojoClient,
5 getGuildForRequest,
6 processDojoBuildMaterialsGathered,
7 setDojoRoomLogFunded
8 } from "@/src/services/guildService";
4 9 import { Types } from "mongoose";
5 10 import { ExportDojoRecipes } from "warframe-public-export-plus";
6 11 import { config } from "@/src/services/configService";
@@ -21,10 +26,20 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
21 26 guild.DojoEnergy += room.energy;
22 27 }
23 28
29 const componentId = new Types.ObjectId();
30
31 guild.RoomChanges ??= [];
32 guild.RoomChanges.push({
33 dateTime: new Date(),
34 entryType: 2,
35 details: request.PlacedComponent.pf,
36 componentId: componentId
37 });
38
24 39 const component =
25 40 guild.DojoComponents[
26 41 guild.DojoComponents.push({
27 _id: new Types.ObjectId(),
42 _id: componentId,
28 43 pf: request.PlacedComponent.pf,
29 44 ppf: request.PlacedComponent.ppf,
30 45 pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
@@ -38,6 +53,7 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
38 53 if (room) {
39 54 processDojoBuildMaterialsGathered(guild, room);
40 55 }
56 setDojoRoomLogFunded(guild, component);
41 57 }
42 58 await guild.save();
43 59 res.json(await getDojoClient(guild, 0));
Modified src/models/guildModel.ts +14 -1
@@ -7,7 +7,8 @@ import {
7 7 IGuildMemberDatabase,
8 8 IGuildLogEntryNumber,
9 9 IGuildLogEntryString,
10 IGuildRank
10 IGuildRank,
11 IGuildLogRoomChange
11 12 } from "@/src/types/guildTypes";
12 13 import { Document, Model, model, Schema, Types } from "mongoose";
13 14 import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
@@ -34,6 +35,7 @@ const dojoComponentSchema = new Schema<IDojoComponentDatabase>({
34 35 RegularCredits: Number,
35 36 MiscItems: { type: [typeCountSchema], default: undefined },
36 37 CompletionTime: Date,
38 CompletionLogPending: Boolean,
37 39 RushPlatinum: Number,
38 40 DestructionTime: Date,
39 41 Decos: [dojoDecoSchema],
@@ -115,6 +117,16 @@ const guildLogEntryStringSchema = new Schema<IGuildLogEntryString>(
115 117 { _id: false }
116 118 );
117 119
120 const guildLogRoomChangeSchema = new Schema<IGuildLogRoomChange>(
121 {
122 dateTime: Date,
123 entryType: Number,
124 details: String,
125 componentId: Types.ObjectId
126 },
127 { _id: false }
128 );
129
118 130 const guildLogEntryNumberSchema = new Schema<IGuildLogEntryNumber>(
119 131 {
120 132 dateTime: Date,
@@ -146,6 +158,7 @@ const guildSchema = new Schema<IGuildDatabase>(
146 158 CeremonyContributors: { type: [Types.ObjectId], default: undefined },
147 159 CeremonyResetDate: Date,
148 160 CeremonyEndo: Number,
161 RoomChanges: { type: [guildLogRoomChangeSchema], default: undefined },
149 162 TechChanges: { type: [guildLogEntryStringSchema], default: undefined },
150 163 RosterActivity: { type: [guildLogEntryStringSchema], default: undefined },
151 164 ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined }
Modified src/services/guildService.ts +33 -3
@@ -6,6 +6,7 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
6 6 import {
7 7 IDojoClient,
8 8 IDojoComponentClient,
9 IDojoComponentDatabase,
9 10 IDojoContributable,
10 11 IDojoDecoClient,
11 12 IGuildClient,
@@ -126,7 +127,8 @@ export const getDojoClient = async (
126 127 DojoComponents: []
127 128 };
128 129 const roomsToRemove: Types.ObjectId[] = [];
129 guild.DojoComponents.forEach(dojoComponent => {
130 let needSave = false;
131 for (const dojoComponent of guild.DojoComponents) {
130 132 if (!componentId || dojoComponent._id.equals(componentId)) {
131 133 const clientComponent: IDojoComponentClient = {
132 134 id: toOid(dojoComponent._id),
@@ -143,10 +145,18 @@ export const getDojoClient = async (
143 145 }
144 146 if (dojoComponent.CompletionTime) {
145 147 clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
148 if (dojoComponent.CompletionLogPending && Date.now() >= dojoComponent.CompletionTime.getTime()) {
149 const entry = guild.RoomChanges?.find(x => x.componentId.equals(dojoComponent._id));
150 if (entry) {
151 dojoComponent.CompletionLogPending = undefined;
152 entry.entryType = 1;
153 needSave = true;
154 }
155 }
146 156 if (dojoComponent.DestructionTime) {
147 157 if (Date.now() >= dojoComponent.DestructionTime.getTime()) {
148 158 roomsToRemove.push(dojoComponent._id);
149 return;
159 continue;
150 160 }
151 161 clientComponent.DestructionTime = toMongoDate(dojoComponent.DestructionTime);
152 162 }
@@ -175,12 +185,15 @@ export const getDojoClient = async (
175 185 }
176 186 dojo.DojoComponents.push(clientComponent);
177 187 }
178 });
188 }
179 189 if (roomsToRemove.length) {
180 190 logger.debug(`removing now-destroyed rooms`, roomsToRemove);
181 191 for (const id of roomsToRemove) {
182 192 removeDojoRoom(guild, id);
183 193 }
194 needSave = true;
195 }
196 if (needSave) {
184 197 await guild.save();
185 198 }
186 199 return dojo;
@@ -203,6 +216,13 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types
203 216 }
204 217 moveResourcesToVault(guild, component);
205 218 component.Decos?.forEach(deco => moveResourcesToVault(guild, deco));
219
220 if (guild.RoomChanges) {
221 const index = guild.RoomChanges.findIndex(x => x.componentId.equals(component._id));
222 if (index != -1) {
223 guild.RoomChanges.splice(index, 1);
224 }
225 }
206 226 };
207 227
208 228 export const removeDojoDeco = (
@@ -254,6 +274,16 @@ export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument,
254 274 }
255 275 };
256 276
277 // guild.save(); is expected some time after this function is called
278 export const setDojoRoomLogFunded = (guild: TGuildDatabaseDocument, component: IDojoComponentDatabase): void => {
279 const entry = guild.RoomChanges?.find(x => x.componentId.equals(component._id));
280 if (entry && entry.entryType == 2) {
281 entry.entryType = 0;
282 entry.dateTime = component.CompletionTime!;
283 component.CompletionLogPending = true;
284 }
285 };
286
257 287 export const fillInInventoryDataForGuildMember = async (member: IGuildMemberClient): Promise<void> => {
258 288 const inventory = await getInventory(member._id.$oid, "PlayerLevel ActiveAvatarImageType");
259 289 member.PlayerLevel = config.spoofMasteryRank == -1 ? inventory.PlayerLevel : config.spoofMasteryRank;
Modified src/types/guildTypes.ts +6 -0
@@ -48,6 +48,7 @@ export interface IGuildDatabase {
48 48 CeremonyContributors?: Types.ObjectId[];
49 49 CeremonyResetDate?: Date;
50 50
51 RoomChanges?: IGuildLogRoomChange[];
51 52 TechChanges?: IGuildLogEntryString[];
52 53 RosterActivity?: IGuildLogEntryString[];
53 54 ClassChanges?: IGuildLogEntryNumber[];
@@ -146,6 +147,7 @@ export interface IDojoComponentDatabase
146 147 _id: Types.ObjectId;
147 148 pi?: Types.ObjectId;
148 149 CompletionTime?: Date;
150 CompletionLogPending?: boolean;
149 151 DestructionTime?: Date;
150 152 Decos?: IDojoDecoDatabase[];
151 153 }
@@ -193,6 +195,10 @@ export interface IGuildLogEntryString {
193 195 details: string;
194 196 }
195 197
198 export interface IGuildLogRoomChange extends IGuildLogEntryString {
199 componentId: Types.ObjectId;
200 }
201
196 202 export interface IGuildLogEntryNumber {
197 203 dateTime: Date;
198 204 entryType: number;