From 988458e22332d495a9eb9c580be902809ae020fc Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:14:55 +0100 Subject: [PATCH] Update types --- types/callbacks/SaveCallbacks.d.ts | 4 +- types/controllers/DialogueController.d.ts | 9 +- types/controllers/QuestController.d.ts | 2 +- .../RepeatableQuestController.d.ts | 14 ++- .../generators/RepeatableQuestGenerator.d.ts | 13 +-- .../RepeatableQuestRewardGenerator.d.ts | 8 +- types/helpers/ProfileHelper.d.ts | 19 ++++ types/models/eft/common/tables/IQuest.d.ts | 7 ++ .../eft/common/tables/IRepeatableQuests.d.ts | 14 +++ .../eft/profile/IGetOtherProfileResponse.d.ts | 2 +- .../eft/profile/ISearchFriendResponse.d.ts | 1 + types/models/eft/profile/ISptProfile.d.ts | 2 + types/models/eft/ws/IWsFriendsListAccept.d.ts | 5 + types/models/eft/ws/IWsNotificationEvent.d.ts | 2 +- types/models/enums/ConfigTypes.d.ts | 1 + types/models/spt/config/IBackupConfig.d.ts | 12 +++ types/models/spt/config/IItemConfig.d.ts | 2 + types/services/BackupService.d.ts | 98 +++++++++++++++++++ types/services/CircleOfCultistService.d.ts | 30 +++--- types/services/ItemFilterService.d.ts | 5 + types/utils/RandomUtil.d.ts | 32 +++++- 21 files changed, 251 insertions(+), 31 deletions(-) create mode 100644 types/models/eft/ws/IWsFriendsListAccept.d.ts create mode 100644 types/models/spt/config/IBackupConfig.d.ts create mode 100644 types/services/BackupService.d.ts diff --git a/types/callbacks/SaveCallbacks.d.ts b/types/callbacks/SaveCallbacks.d.ts index 8f836cb7..3d5f2126 100644 --- a/types/callbacks/SaveCallbacks.d.ts +++ b/types/callbacks/SaveCallbacks.d.ts @@ -3,11 +3,13 @@ import { OnUpdate } from "@spt/di/OnUpdate"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { BackupService } from "@spt/services/BackupService"; export declare class SaveCallbacks implements OnLoad, OnUpdate { protected saveServer: SaveServer; protected configServer: ConfigServer; + protected backupService: BackupService; protected coreConfig: ICoreConfig; - constructor(saveServer: SaveServer, configServer: ConfigServer); + constructor(saveServer: SaveServer, configServer: ConfigServer, backupService: BackupService); onLoad(): Promise; getRoute(): string; onUpdate(secondsSinceLastRun: number): Promise; diff --git a/types/controllers/DialogueController.d.ts b/types/controllers/DialogueController.d.ts index 2f00b131..ded87cf6 100644 --- a/types/controllers/DialogueController.d.ts +++ b/types/controllers/DialogueController.d.ts @@ -1,5 +1,8 @@ import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; +import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; +import { ProfileHelper } from "@spt/helpers/ProfileHelper"; +import { IDeleteFriendRequest } from "@spt/models/eft/dialog/IDeleteFriendRequest"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse"; import { IGetAllAttachmentsResponse } from "@spt/models/eft/dialog/IGetAllAttachmentsResponse"; @@ -20,11 +23,13 @@ export declare class DialogueController { protected saveServer: SaveServer; protected timeUtil: TimeUtil; protected dialogueHelper: DialogueHelper; + protected notificationSendHelper: NotificationSendHelper; + protected profileHelper: ProfileHelper; protected mailSendService: MailSendService; protected localisationService: LocalisationService; protected configServer: ConfigServer; protected dialogueChatBots: IDialogueChatBot[]; - constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); + constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, notificationSendHelper: NotificationSendHelper, profileHelper: ProfileHelper, mailSendService: MailSendService, localisationService: LocalisationService, configServer: ConfigServer, dialogueChatBots: IDialogueChatBot[]); registerChatBot(chatBot: IDialogueChatBot): void; /** Handle onUpdate spt event */ update(): void; @@ -151,4 +156,6 @@ export declare class DialogueController { protected messageHasExpired(message: IMessage): boolean; /** Handle client/friend/request/send */ sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse; + /** Handle client/friend/delete */ + deleteFriend(sessionID: string, request: IDeleteFriendRequest): void; } diff --git a/types/controllers/QuestController.d.ts b/types/controllers/QuestController.d.ts index ac486e38..85221d68 100644 --- a/types/controllers/QuestController.d.ts +++ b/types/controllers/QuestController.d.ts @@ -72,6 +72,7 @@ export declare class QuestController { */ protected addTaskConditionCountersToProfile(questConditions: IQuestCondition[], pmcData: IPmcData, questId: string): void; /** + * TODO - Move this code into RepeatableQuestController * Handle the client accepting a repeatable quest and starting it * Send starting rewards if any to player and * Send start notification if any to player @@ -81,7 +82,6 @@ export declare class QuestController { * @returns IItemEventRouterResponse */ acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; - protected createAcceptedQuestClientResponse(sessionID: string, pmcData: IPmcData, repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse; /** * Look for an accepted quest inside player profile, return matching * @param pmcData Profile to search through diff --git a/types/controllers/RepeatableQuestController.d.ts b/types/controllers/RepeatableQuestController.d.ts index 016f8c61..87257cae 100644 --- a/types/controllers/RepeatableQuestController.d.ts +++ b/types/controllers/RepeatableQuestController.d.ts @@ -147,6 +147,18 @@ export declare class RepeatableQuestController { * @returns IItemEventRouterResponse */ changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse; + /** + * Remove the provided quest from pmc and scav character profiles + * @param fullProfile Profile to remove quest from + * @param questToReplaceId Quest id to remove from profile + */ + protected removeQuestFromProfile(fullProfile: ISptProfile, questToReplaceId: string): void; + /** + * Clean up the repeatables `changeRequirement` dictionary of expired data + * @param repeatablesOfTypeInProfile The repeatables that have the replaced and new quest + * @param replacedQuestId Id of the replaced quest + */ + protected cleanUpRepeatableChangeRequirements(repeatablesOfTypeInProfile: IPmcDataRepeatableQuest, replacedQuestId: string): void; /** * Find a repeatable (daily/weekly/scav) from a players profile by its id * @param questId Id of quest to find @@ -154,7 +166,7 @@ export declare class RepeatableQuestController { * @returns IGetRepeatableByIdResult */ protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult; - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected attemptToGenerateRepeatableQuest(sessionId: string, pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Some accounts have access to free repeatable quest refreshes * Track the usage of them inside players profile diff --git a/types/generators/RepeatableQuestGenerator.d.ts b/types/generators/RepeatableQuestGenerator.d.ts index 79a10fc3..802a68b6 100644 --- a/types/generators/RepeatableQuestGenerator.d.ts +++ b/types/generators/RepeatableQuestGenerator.d.ts @@ -33,13 +33,14 @@ export declare class RepeatableQuestGenerator { /** * This method is called by /GetClientRepeatableQuests/ and creates one element of quest type format (see assets/database/templates/repeatableQuests.json). * It randomly draws a quest type (currently Elimination, Completion or Exploration) as well as a trader who is providing the quest + * @param sessionId Session id * @param pmcLevel Player's level for requested items and reward generation * @param pmcTraderInfo Players traper standing/rep levels * @param questTypePool Possible quest types pool * @param repeatableConfig Repeatable quest config * @returns IRepeatableQuest */ - generateRepeatableQuest(pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + generateRepeatableQuest(sessionId: string, pmcLevel: number, pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Generate a randomised Elimination quest * @param pmcLevel Player's level for requested items and reward generation @@ -48,7 +49,7 @@ export declare class RepeatableQuestGenerator { * @param repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns Object of quest type format for "Elimination" (see assets/database/templates/repeatableQuests.json) */ - protected generateEliminationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateEliminationQuest(sessionid: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Get a number of kills neded to complete elimination quest * @param targetKey Target type desired e.g. anyPmc/bossBully/Savage @@ -83,7 +84,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Completion" (see assets/database/templates/repeatableQuests.json) */ - protected generateCompletionQuest(pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateCompletionQuest(sessionId: string, pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * A repeatable quest, besides some more or less static components, exists of reward and condition (see assets/database/templates/repeatableQuests.json) * This is a helper method for GenerateCompletionQuest to create a completion condition (of which a completion quest theoretically can have many) @@ -102,7 +103,7 @@ export declare class RepeatableQuestGenerator { * @param {object} repeatableConfig The configuration for the repeatably kind (daily, weekly) as configured in QuestConfig for the requestd quest * @returns {object} object of quest type format for "Exploration" (see assets/database/templates/repeatableQuests.json) */ - protected generateExplorationQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generateExplorationQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Filter a maps exits to just those for the desired side * @param locationKey Map id (e.g. factory4_day) @@ -110,7 +111,7 @@ export declare class RepeatableQuestGenerator { * @returns Array of Exit objects */ protected getLocationExitsForSide(locationKey: string, playerSide: string): IExit[]; - protected generatePickupQuest(pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; + protected generatePickupQuest(sessionId: string, pmcLevel: number, traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest; /** * Convert a location into an quest code can read (e.g. factory4_day into 55f2d3fd4bdc2d5f408b4567) * @param locationKey e.g factory4_day @@ -135,5 +136,5 @@ export declare class RepeatableQuestGenerator { * @returns {object} Object which contains the base elements for repeatable quests of the requests type * (needs to be filled with reward and conditions by called to make a valid quest) */ - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest; + protected generateRepeatableTemplate(type: string, traderId: string, side: string, sessionId: string): IRepeatableQuest; } diff --git a/types/generators/RepeatableQuestRewardGenerator.d.ts b/types/generators/RepeatableQuestRewardGenerator.d.ts index bc78ccad..f029974d 100644 --- a/types/generators/RepeatableQuestRewardGenerator.d.ts +++ b/types/generators/RepeatableQuestRewardGenerator.d.ts @@ -12,6 +12,7 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; @@ -19,6 +20,7 @@ import { ICloner } from "@spt/utils/cloners/ICloner"; export declare class RepeatableQuestRewardGenerator { protected logger: ILogger; protected randomUtil: RandomUtil; + protected hashUtil: HashUtil; protected mathUtil: MathUtil; protected databaseService: DatabaseService; protected itemHelper: ItemHelper; @@ -31,7 +33,7 @@ export declare class RepeatableQuestRewardGenerator { protected configServer: ConfigServer; protected cloner: ICloner; protected questConfig: IQuestConfig; - constructor(logger: ILogger, randomUtil: RandomUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); + constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, mathUtil: MathUtil, databaseService: DatabaseService, itemHelper: ItemHelper, presetHelper: PresetHelper, handbookHelper: HandbookHelper, localisationService: LocalisationService, objectId: ObjectId, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService, configServer: ConfigServer, cloner: ICloner); /** * Generate the reward for a mission. A reward can consist of: * - Experience @@ -127,7 +129,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward; + protected generateItemReward(tpl: string, count: number, index: number, foundInRaid?: boolean): IQuestReward; /** * Helper to create a reward item structured as required by the client * @@ -137,7 +139,7 @@ export declare class RepeatableQuestRewardGenerator { * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[]): IQuestReward; + protected generatePresetReward(tpl: string, count: number, index: number, preset?: IItem[], foundInRaid?: boolean): IQuestReward; /** * Picks rewardable items from items.json * This means they must: diff --git a/types/helpers/ProfileHelper.d.ts b/types/helpers/ProfileHelper.d.ts index c2871b44..f68c5809 100644 --- a/types/helpers/ProfileHelper.d.ts +++ b/types/helpers/ProfileHelper.d.ts @@ -2,6 +2,7 @@ import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Common, ICounterKeyValue, IStats } from "@spt/models/eft/common/tables/IBotBase"; import { IItem } from "@spt/models/eft/common/tables/IItem"; +import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { BonusType } from "@spt/models/enums/BonusType"; @@ -90,6 +91,24 @@ export declare class ProfileHelper { * @returns ISptProfile object */ getFullProfile(sessionID: string): ISptProfile | undefined; + /** + * Get full representation of a players profile JSON by the account ID, or undefined if not found + * @param accountId Account ID to find + * @returns + */ + getFullProfileByAccountId(accountID: string): ISptProfile | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given session ID + * @param sessionID The session ID to return the profile for + * @returns + */ + getChatRoomMemberFromSessionId(sessionID: string): ISearchFriendResponse | undefined; + /** + * Retrieve a ChatRoomMember formatted profile for the given PMC profile data + * @param pmcProfile The PMC profile data to format into a ChatRoomMember structure + * @returns + */ + getChatRoomMemberFromPmcProfile(pmcProfile: IPmcData): ISearchFriendResponse; /** * Get a PMC profile by its session id * @param sessionID Profile id to return diff --git a/types/models/eft/common/tables/IQuest.d.ts b/types/models/eft/common/tables/IQuest.d.ts index e9568562..3d1e9e3c 100644 --- a/types/models/eft/common/tables/IQuest.d.ts +++ b/types/models/eft/common/tables/IQuest.d.ts @@ -33,6 +33,11 @@ export interface IQuest { changeQuestMessageText: string; /** "Pmc" or "Scav" */ side: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; /** Status of quest to player */ sptStatus?: QuestStatus; } @@ -148,8 +153,10 @@ export interface IQuestReward { loyaltyLevel?: number; /** Hideout area id */ traderId?: string; + isEncoded?: boolean; unknown?: boolean; findInRaid?: boolean; + gameMode?: string[]; /** Game editions whitelisted to get reward */ availableInGameEditions?: string[]; /** Game editions blacklisted from getting reward */ diff --git a/types/models/eft/common/tables/IRepeatableQuests.d.ts b/types/models/eft/common/tables/IRepeatableQuests.d.ts index 37e582a6..b596c2b7 100644 --- a/types/models/eft/common/tables/IRepeatableQuests.d.ts +++ b/types/models/eft/common/tables/IRepeatableQuests.d.ts @@ -3,6 +3,12 @@ export interface IRepeatableQuest extends IQuest { changeCost: IChangeCost[]; changeStandingCost: number; sptRepatableGroupName: string; + acceptanceAndFinishingSource: string; + progressSource: string; + rankingModes: string[]; + gameModes: string[]; + arenaLocations: string[]; + questStatus: IRepeatableQuestStatus; } export interface IRepeatableQuestDatabase { templates: IRepeatableTemplates; @@ -10,6 +16,14 @@ export interface IRepeatableQuestDatabase { data: IOptions; samples: ISampleQuests[]; } +export interface IRepeatableQuestStatus { + id: string; + uid: string; + qid: string; + startTime: number; + status: number; + statusTimers: any; +} export interface IRepeatableTemplates { Elimination: IQuest; Completion: IQuest; diff --git a/types/models/eft/profile/IGetOtherProfileResponse.d.ts b/types/models/eft/profile/IGetOtherProfileResponse.d.ts index 88a49b4f..0b4683a1 100644 --- a/types/models/eft/profile/IGetOtherProfileResponse.d.ts +++ b/types/models/eft/profile/IGetOtherProfileResponse.d.ts @@ -8,7 +8,7 @@ export interface IGetOtherProfileResponse { skills: ISkills; equipment: IOtherProfileEquipment; achievements: Record; - favoriteItems: string[]; + favoriteItems: IItem[]; pmcStats: IOtherProfileStats; scavStats: IOtherProfileStats; } diff --git a/types/models/eft/profile/ISearchFriendResponse.d.ts b/types/models/eft/profile/ISearchFriendResponse.d.ts index d3cc7dfd..628b82ce 100644 --- a/types/models/eft/profile/ISearchFriendResponse.d.ts +++ b/types/models/eft/profile/ISearchFriendResponse.d.ts @@ -8,4 +8,5 @@ export interface Info { Side: string; Level: number; MemberCategory: number; + SelectedMemberCategory: number; } diff --git a/types/models/eft/profile/ISptProfile.d.ts b/types/models/eft/profile/ISptProfile.d.ts index aba539b4..af8c92f3 100644 --- a/types/models/eft/profile/ISptProfile.d.ts +++ b/types/models/eft/profile/ISptProfile.d.ts @@ -19,6 +19,8 @@ export interface ISptProfile { traderPurchases?: Record>; /** Achievements earned by player */ achievements: Record; + /** List of friend profile IDs */ + friends: string[]; } export declare class ITraderPurchaseData { count: number; diff --git a/types/models/eft/ws/IWsFriendsListAccept.d.ts b/types/models/eft/ws/IWsFriendsListAccept.d.ts new file mode 100644 index 00000000..4a96db3c --- /dev/null +++ b/types/models/eft/ws/IWsFriendsListAccept.d.ts @@ -0,0 +1,5 @@ +import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { ISearchFriendResponse } from "../profile/ISearchFriendResponse"; +export interface IWsFriendsListAccept extends IWsNotificationEvent { + profile: ISearchFriendResponse; +} diff --git a/types/models/eft/ws/IWsNotificationEvent.d.ts b/types/models/eft/ws/IWsNotificationEvent.d.ts index 5fc72f3a..de119c8d 100644 --- a/types/models/eft/ws/IWsNotificationEvent.d.ts +++ b/types/models/eft/ws/IWsNotificationEvent.d.ts @@ -1,4 +1,4 @@ export interface IWsNotificationEvent { type: string; - eventId: string; + eventId?: string; } diff --git a/types/models/enums/ConfigTypes.d.ts b/types/models/enums/ConfigTypes.d.ts index 2c4483a9..5bed6f17 100644 --- a/types/models/enums/ConfigTypes.d.ts +++ b/types/models/enums/ConfigTypes.d.ts @@ -1,5 +1,6 @@ export declare enum ConfigTypes { AIRDROP = "spt-airdrop", + BACKUP = "spt-backup", BOT = "spt-bot", PMC = "spt-pmc", CORE = "spt-core", diff --git a/types/models/spt/config/IBackupConfig.d.ts b/types/models/spt/config/IBackupConfig.d.ts new file mode 100644 index 00000000..06bb7475 --- /dev/null +++ b/types/models/spt/config/IBackupConfig.d.ts @@ -0,0 +1,12 @@ +import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; +export interface IBackupConfig extends IBaseConfig { + kind: "spt-backup"; + enabled: boolean; + maxBackups: number; + directory: string; + backupInterval: IBackupConfigInterval; +} +export interface IBackupConfigInterval { + enabled: boolean; + intervalMinutes: number; +} diff --git a/types/models/spt/config/IItemConfig.d.ts b/types/models/spt/config/IItemConfig.d.ts index a8833bf0..d516ba9b 100644 --- a/types/models/spt/config/IItemConfig.d.ts +++ b/types/models/spt/config/IItemConfig.d.ts @@ -7,6 +7,8 @@ export interface IItemConfig extends IBaseConfig { lootableItemBlacklist: string[]; /** items that should not be given as rewards */ rewardItemBlacklist: string[]; + /** Item base types that should not be given as rewards */ + rewardItemTypeBlacklist: string[]; /** Items that can only be found on bosses */ bossItems: string[]; handbookPriceOverride: Record; diff --git a/types/services/BackupService.d.ts b/types/services/BackupService.d.ts new file mode 100644 index 00000000..aeab6c14 --- /dev/null +++ b/types/services/BackupService.d.ts @@ -0,0 +1,98 @@ +import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; +import { IBackupConfig } from "@spt/models/spt/config/IBackupConfig"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { ConfigServer } from "@spt/servers/ConfigServer"; +export declare class BackupService { + protected logger: ILogger; + protected preSptModLoader: PreSptModLoader; + protected configServer: ConfigServer; + protected backupConfig: IBackupConfig; + protected readonly activeServerMods: string[]; + protected readonly profileDir = "./user/profiles"; + constructor(logger: ILogger, preSptModLoader: PreSptModLoader, configServer: ConfigServer); + /** + * Initializes the backup process. + * + * This method orchestrates the profile backup service. Handles copying profiles to a backup directory and cleaning + * up old backups if the number exceeds the configured maximum. + * + * @returns A promise that resolves when the backup process is complete. + */ + init(): Promise; + /** + * Fetches the names of all JSON files in the profile directory. + * + * This method normalizes the profile directory path and reads all files within it. It then filters the files to + * include only those with a `.json` extension and returns their names. + * + * @returns A promise that resolves to an array of JSON file names. + */ + protected fetchProfileFiles(): Promise; + /** + * Check to see if the backup service is enabled via the config. + * + * @returns True if enabled, false otherwise. + */ + protected isEnabled(): boolean; + /** + * Generates the target directory path for the backup. The directory path is constructed using the `directory` from + * the configuration and the current backup date. + * + * @returns The target directory path for the backup. + */ + protected generateBackupTargetDir(): string; + /** + * Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`. + * + * @returns The formatted backup date string. + */ + protected generateBackupDate(): string; + /** + * Cleans up old backups in the backup directory. + * + * This method reads the backup directory, and sorts backups by modification time. If the number of backups exceeds + * the configured maximum, it deletes the oldest backups. + * + * @returns A promise that resolves when the cleanup is complete. + */ + protected cleanBackups(): Promise; + /** + * Retrieves and sorts the backup file paths from the specified directory. + * + * @param dir - The directory to search for backup files. + * @returns A promise that resolves to an array of sorted backup file paths. + */ + private getBackupPaths; + /** + * Compares two backup folder names based on their extracted dates. + * + * @param a - The name of the first backup folder. + * @param b - The name of the second backup folder. + * @returns The difference in time between the two dates in milliseconds, or `null` if either date is invalid. + */ + private compareBackupDates; + /** + * Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`. + * + * @param folderName - The name of the folder from which to extract the date. + * @returns A Date object if the folder name is in the correct format, otherwise null. + */ + private extractDateFromFolderName; + /** + * Removes excess backups from the backup directory. + * + * @param backups - An array of backup file names to be removed. + * @returns A promise that resolves when all specified backups have been removed. + */ + private removeExcessBackups; + /** + * Start the backup interval if enabled in the configuration. + */ + protected startBackupInterval(): void; + /** + * Get an array of active server mod details. + * + * @returns An array of mod names. + */ + protected getActiveServerMods(): string[]; +} diff --git a/types/services/CircleOfCultistService.d.ts b/types/services/CircleOfCultistService.d.ts index e7334146..7568261e 100644 --- a/types/services/CircleOfCultistService.d.ts +++ b/types/services/CircleOfCultistService.d.ts @@ -54,6 +54,16 @@ export declare class CircleOfCultistService { * @returns IItemEventRouterResponse */ startSacrifice(sessionId: string, pmcData: IPmcData, request: IHideoutCircleOfCultistProductionStartRequestData): IItemEventRouterResponse; + /** + * Attempt to add all rewards to cultist circle, if they dont fit remove one and try again until they fit + * @param sessionId Session id + * @param pmcData Player profile + * @param rewards Rewards to send to player + * @param containerGrid Cultist grid to add rewards to + * @param cultistCircleStashId Stash id + * @param output Client output + */ + protected addRewardsToCircleContainer(sessionId: string, pmcData: IPmcData, rewards: IItem[][], containerGrid: number[][], cultistCircleStashId: string, output: IItemEventRouterResponse): void; /** * Create a map of the possible direct rewards, keyed by the items needed to be sacrificed * @param directRewards Direct rewards array from hideout config @@ -156,7 +166,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addTaskItemRequirementsToRewardPool(pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Adds items the player needs to complete hideout crafts/upgrades to the reward pool * @param hideoutDbData Hideout area data @@ -164,7 +174,7 @@ export declare class CircleOfCultistService { * @param itemRewardBlacklist Items not to add to pool * @param rewardPool Pool to add items to */ - protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: string[], rewardPool: Set): void; + protected addHideoutUpgradeRequirementsToRewardPool(hideoutDbData: IHideout, pmcData: IPmcData, itemRewardBlacklist: Set, rewardPool: Set): void; /** * Get all active hideout areas * @param areas Hideout areas to iterate over @@ -174,11 +184,11 @@ export declare class CircleOfCultistService { /** * Get array of random reward items * @param rewardPool Reward pool to add to - * @param itemRewardBlacklist Reward Blacklist + * @param itemRewardBlacklist Item tpls to ignore * @param itemsShouldBeHighValue Should these items meet the valuable threshold - * @returns rewardPool + * @returns Set of item tpls */ - protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: string[], itemsShouldBeHighValue: boolean): Set; + protected generateRandomisedItemsAndAddToRewardPool(rewardPool: Set, itemRewardBlacklist: Set, itemsShouldBeHighValue: boolean): Set; /** * Iterate over passed in hideout requirements and return the Item * @param requirements Requirements to iterate over @@ -186,13 +196,3 @@ export declare class CircleOfCultistService { */ protected getItemRequirements(requirements: IRequirementBase[]): (IStageRequirement | IRequirement)[]; } -export declare enum CircleRewardType { - RANDOM = 0, - HIDEOUT_TASK = 1 -} -export interface ICraftDetails { - time: number; - rewardType: CircleRewardType; - rewardAmountRoubles: number; - rewardDetails?: ICraftTimeThreshhold; -} diff --git a/types/services/ItemFilterService.d.ts b/types/services/ItemFilterService.d.ts index 7ff65324..120d44e8 100644 --- a/types/services/ItemFilterService.d.ts +++ b/types/services/ItemFilterService.d.ts @@ -36,6 +36,11 @@ export declare class ItemFilterService { * @returns string array of item tpls */ getItemRewardBlacklist(): string[]; + /** + * Get an array of item types that should never be given as a reward to player + * @returns string array of item base ids + */ + getItemRewardBaseTypeBlacklist(): string[]; /** * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids diff --git a/types/utils/RandomUtil.d.ts b/types/utils/RandomUtil.d.ts index 601300cc..a94c336d 100644 --- a/types/utils/RandomUtil.d.ts +++ b/types/utils/RandomUtil.d.ts @@ -106,6 +106,11 @@ export declare class RandomUtil { protected cloner: ICloner; protected logger: ILogger; constructor(cloner: ICloner, logger: ILogger); + /** + * The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both + * integer + fractional parts) to about 15–17 significant digits. 15 is a safe upper bound, so we'll use that. + */ + private static readonly MAX_SIGNIFICANT_DIGITS; /** * Generates a secure random number between 0 (inclusive) and 1 (exclusive). * @@ -116,6 +121,16 @@ export declare class RandomUtil { * @returns A secure random number between 0 (inclusive) and 1 (exclusive). */ private getSecureRandomNumber; + /** + * Determines the number of decimal places in a number. + * + * @param num - The number to analyze. + * @returns The number of decimal places, or 0 if none exist. + * @remarks There is a mathematical way to determine this, but it's not as simple as it seams due to floating point + * precision issues. This method is a simple workaround that converts the number to a string and splits it. + * It's not the most efficient but it *is* the most reliable and easy to understand. Come at me. + */ + private getNumberPrecision; /** * Generates a random integer between the specified minimum and maximum values, inclusive. * @@ -173,7 +188,7 @@ export declare class RandomUtil { /** * Returns a random string from the provided array of strings. * - * This method is separate from getArrayValue so we can use a generic inferance with getArrayValue. + * This method is separate from getArrayValue so we can use a generic inference with getArrayValue. * * @param arr - The array of strings to select a random value from. * @returns A randomly selected string from the array. @@ -225,12 +240,27 @@ export declare class RandomUtil { getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt?: number): number; /** * Generates a random integer between the specified range. + * Low and high parameters are floored to integers. + * + * TODO: v3.11 - This method should not accept non-integer numbers. * * @param low - The lower bound of the range (inclusive). * @param high - The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. * @returns A random integer within the specified range. */ randInt(low: number, high?: number): number; + /** + * Generates a random number between two given values with optional precision. + * + * @param value1 - The first value to determine the range. + * @param value2 - The second value to determine the range. If not provided, 0 is used. + * @param precision - The number of decimal places to round the result to. Must be a positive integer between 0 + * and MAX_PRECISION, inclusive. If not provided, precision is determined by the input values. + * @returns A random floating-point number between `value1` and `value2` (inclusive) with the specified precision. + * @throws Will throw an error if `precision` is not a positive integer, if `value1` or `value2` are not finite + * numbers, or if the precision exceeds the maximum allowed for the given values. + */ + randNum(value1: number, value2?: number, precision?: number | null): number; /** * Draws a specified number of random elements from a given list. *