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

SpaceNinjaServer

A simple server for a small space ninja game

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

XFEstudio/SpaceNinjaServer

feat: track vendor purchases (#1153)

Closes #739 Also adds the `noVendorPurchaseLimits` cheat to disable the logic, which is enabled by default due to lack of vendor rotations. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1153

6490fadc
Sainan <sainan@calamity.inc>
提交于

代码差异

10 个文件 +104 -3
Modified config.json.example +1 -0
@@ -29,6 +29,7 @@
29 29 "unlockExilusEverywhere": false,
30 30 "unlockArcanesEverywhere": false,
31 31 "noDailyStandingLimits": false,
32 "noVendorPurchaseLimits": true,
32 33 "instantResourceExtractorDrones": false,
33 34 "noDojoRoomBuildStage": false,
34 35 "fastDojoRoomDestruction": false,
Modified src/models/inventoryModels/inventoryModel.ts +30 -2
@@ -76,7 +76,10 @@ import {
76 76 IIncentiveState,
77 77 ISongChallenge,
78 78 ILibraryPersonalProgress,
79 ICrewShipWeaponDatabase
79 ICrewShipWeaponDatabase,
80 IRecentVendorPurchaseDatabase,
81 IVendorPurchaseHistoryEntryDatabase,
82 IVendorPurchaseHistoryEntryClient
80 83 } from "../../types/inventoryTypes/inventoryTypes";
81 84 import { IOid } from "../../types/commonTypes";
82 85 import {
@@ -974,6 +977,31 @@ const incentiveStateSchema = new Schema<IIncentiveState>(
974 977 { _id: false }
975 978 );
976 979
980 const vendorPurchaseHistoryEntrySchema = new Schema<IVendorPurchaseHistoryEntryDatabase>(
981 {
982 Expiry: Date,
983 NumPurchased: Number,
984 ItemId: String
985 },
986 { _id: false }
987 );
988
989 vendorPurchaseHistoryEntrySchema.set("toJSON", {
990 transform(_doc, obj) {
991 const db = obj as IVendorPurchaseHistoryEntryDatabase;
992 const client = obj as IVendorPurchaseHistoryEntryClient;
993 client.Expiry = toMongoDate(db.Expiry);
994 }
995 });
996
997 const recentVendorPurchaseSchema = new Schema<IRecentVendorPurchaseDatabase>(
998 {
999 VendorType: String,
1000 PurchaseHistory: [vendorPurchaseHistoryEntrySchema]
1001 },
1002 { _id: false }
1003 );
1004
977 1005 const collectibleEntrySchema = new Schema<ICollectibleEntry>(
978 1006 {
979 1007 CollectibleType: String,
@@ -1361,7 +1389,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1361 1389 RandomUpgradesIdentified: Number,
1362 1390 BountyScore: Number,
1363 1391 ChallengeInstanceStates: [Schema.Types.Mixed],
1364 RecentVendorPurchases: [Schema.Types.Mixed],
1392 RecentVendorPurchases: { type: [recentVendorPurchaseSchema], default: undefined },
1365 1393 Robotics: [Schema.Types.Mixed],
1366 1394 UsedDailyDeals: [Schema.Types.Mixed],
1367 1395 CollectibleSeries: { type: [collectibleEntrySchema], default: undefined },
Modified src/services/configService.ts +1 -0
@@ -55,6 +55,7 @@ interface IConfig {
55 55 unlockExilusEverywhere?: boolean;
56 56 unlockArcanesEverywhere?: boolean;
57 57 noDailyStandingLimits?: boolean;
58 noVendorPurchaseLimits?: boolean;
58 59 instantResourceExtractorDrones?: boolean;
59 60 noDojoRoomBuildStage?: boolean;
60 61 fastDojoRoomDestruction?: boolean;
Modified src/services/purchaseService.ts +39 -0
@@ -68,6 +68,45 @@ export const handlePurchase = async (
68 68 inventoryChanges
69 69 );
70 70 }
71 if (!config.noVendorPurchaseLimits) {
72 inventory.RecentVendorPurchases ??= [];
73 let vendorPurchases = inventory.RecentVendorPurchases.find(
74 x => x.VendorType == manifest.VendorInfo.TypeName
75 );
76 if (!vendorPurchases) {
77 vendorPurchases =
78 inventory.RecentVendorPurchases[
79 inventory.RecentVendorPurchases.push({
80 VendorType: manifest.VendorInfo.TypeName,
81 PurchaseHistory: []
82 }) - 1
83 ];
84 }
85 const historyEntry = vendorPurchases.PurchaseHistory.find(x => x.ItemId == ItemId);
86 let numPurchased = purchaseRequest.PurchaseParams.Quantity;
87 if (historyEntry) {
88 numPurchased += historyEntry.NumPurchased;
89 historyEntry.NumPurchased += purchaseRequest.PurchaseParams.Quantity;
90 } else {
91 vendorPurchases.PurchaseHistory.push({
92 ItemId: ItemId,
93 NumPurchased: purchaseRequest.PurchaseParams.Quantity,
94 Expiry: new Date(parseInt(offer.Expiry.$date.$numberLong))
95 });
96 }
97 inventoryChanges.RecentVendorPurchases = [
98 {
99 VendorType: manifest.VendorInfo.TypeName,
100 PurchaseHistory: [
101 {
102 ItemId: ItemId,
103 NumPurchased: numPurchased,
104 Expiry: offer.Expiry
105 }
106 ]
107 }
108 ];
109 }
71 110 purchaseRequest.PurchaseParams.Quantity *= offer.QuantityMultiplier;
72 111 } else if (!ExportVendors[purchaseRequest.PurchaseParams.SourceId!]) {
73 112 throw new Error(`unknown vendor: ${purchaseRequest.PurchaseParams.SourceId!}`);
Modified src/types/inventoryTypes/inventoryTypes.ts +25 -1
@@ -41,6 +41,7 @@ export interface IInventoryDatabase
41 41 | "KubrowPetEggs"
42 42 | "PendingCoupon"
43 43 | "Drones"
44 | "RecentVendorPurchases"
44 45 | TEquipmentKey
45 46 >,
46 47 InventoryDatabaseEquipment {
@@ -67,6 +68,7 @@ export interface IInventoryDatabase
67 68 KubrowPetEggs?: IKubrowPetEggDatabase[];
68 69 PendingCoupon?: IPendingCouponDatabase;
69 70 Drones: IDroneDatabase[];
71 RecentVendorPurchases?: IRecentVendorPurchaseDatabase[];
70 72 }
71 73
72 74 export interface IQuestKeyDatabase {
@@ -277,7 +279,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
277 279 BountyScore: number;
278 280 ChallengeInstanceStates: IChallengeInstanceState[];
279 281 LoginMilestoneRewards: string[];
280 RecentVendorPurchases: Array<number | string>;
282 RecentVendorPurchases?: IRecentVendorPurchaseClient[];
281 283 NodeIntrosCompleted: string[];
282 284 GuildId?: IOid;
283 285 CompletedJobChains: ICompletedJobChain[];
@@ -361,6 +363,28 @@ export interface IParam {
361 363 v: string;
362 364 }
363 365
366 export interface IRecentVendorPurchaseClient {
367 VendorType: string;
368 PurchaseHistory: IVendorPurchaseHistoryEntryClient[];
369 }
370
371 export interface IVendorPurchaseHistoryEntryClient {
372 Expiry: IMongoDate;
373 NumPurchased: number;
374 ItemId: string;
375 }
376
377 export interface IRecentVendorPurchaseDatabase {
378 VendorType: string;
379 PurchaseHistory: IVendorPurchaseHistoryEntryDatabase[];
380 }
381
382 export interface IVendorPurchaseHistoryEntryDatabase {
383 Expiry: Date;
384 NumPurchased: number;
385 ItemId: string;
386 }
387
364 388 export interface IChallengeProgress {
365 389 Progress: number;
366 390 Name: string;
Modified static/webui/index.html +4 -0
@@ -517,6 +517,10 @@
517 517 <input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
518 518 <label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
519 519 </div>
520 <div class="form-check">
521 <input class="form-check-input" type="checkbox" id="noVendorPurchaseLimits" />
522 <label class="form-check-label" for="noVendorPurchaseLimits" data-loc="cheats_noVendorPurchaseLimits"></label>
523 </div>
520 524 <div class="form-check">
521 525 <input class="form-check-input" type="checkbox" id="instantResourceExtractorDrones" />
522 526 <label class="form-check-label" for="instantResourceExtractorDrones" data-loc="cheats_instantResourceExtractorDrones"></label>
Modified static/webui/translations/de.js +1 -0
@@ -110,6 +110,7 @@ dict = {
110 110 cheats_unlockExilusEverywhere: `Exilus-Adapter überall`,
111 111 cheats_unlockArcanesEverywhere: `Arkana-Adapter überall`,
112 112 cheats_noDailyStandingLimits: `Kein tägliches Ansehenslimit`,
113 cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
113 114 cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
114 115 cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
115 116 cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
Modified static/webui/translations/en.js +1 -0
@@ -109,6 +109,7 @@ dict = {
109 109 cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
110 110 cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
111 111 cheats_noDailyStandingLimits: `No Daily Standing Limits`,
112 cheats_noVendorPurchaseLimits: `No Vendor Purchase Limits`,
112 113 cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
113 114 cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
114 115 cheats_fastDojoRoomDestruction: `Fast Dojo Room Destruction`,
Modified static/webui/translations/fr.js +1 -0
@@ -110,6 +110,7 @@ dict = {
110 110 cheats_unlockExilusEverywhere: `Adaptateurs Exilus partout`,
111 111 cheats_unlockArcanesEverywhere: `Adaptateur d'Arcanes partout`,
112 112 cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`,
113 cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
113 114 cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`,
114 115 cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
115 116 cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`,
Modified static/webui/translations/ru.js +1 -0
@@ -110,6 +110,7 @@ dict = {
110 110 cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
111 111 cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
112 112 cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
113 cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
113 114 cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`,
114 115 cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`,
115 116 cheats_fastDojoRoomDestruction: `Мгновенные Уничтожение Комнат Додзё`,