返回提交历史
Modified
config.json.example
+1
-0
Modified
src/models/inventoryModels/inventoryModel.ts
+30
-2
Modified
src/services/configService.ts
+1
-0
Modified
src/services/purchaseService.ts
+39
-0
Modified
src/types/inventoryTypes/inventoryTypes.ts
+25
-1
Modified
static/webui/index.html
+4
-0
Modified
static/webui/translations/de.js
+1
-0
Modified
static/webui/translations/en.js
+1
-0
Modified
static/webui/translations/fr.js
+1
-0
Modified
static/webui/translations/ru.js
+1
-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
代码差异
10 个文件
+104
-3
@@ -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,
@@ -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 },
@@ -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;
@@ -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!}`);
@@ -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;
@@ -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>
@@ -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`,
@@ -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`,
@@ -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`,
@@ -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: `Мгновенные Уничтожение Комнат Додзё`,