Merge pull request #108 from tetrisdev/ServersComments
Change Services Comments
This commit is contained in:
@@ -44,9 +44,9 @@ public class BackupService
|
||||
_backupConfig = configServer.GetConfig<BackupConfig>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the backup interval if enabled in config.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Start the backup interval if enabled in config.
|
||||
/// </summary>
|
||||
public void StartBackupSystem()
|
||||
{
|
||||
if (!_backupConfig.BackupInterval.Enabled)
|
||||
@@ -75,14 +75,11 @@ public class BackupService
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Initializes the backup process. <br/>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public void Init()
|
||||
{
|
||||
if (!IsEnabled())
|
||||
@@ -146,11 +143,10 @@ public class BackupService
|
||||
CleanBackups();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the backup service is enabled via the config.
|
||||
*
|
||||
* @returns True if enabled, false otherwise.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check to see if the backup service is enabled via the config.
|
||||
/// </summary>
|
||||
/// <returns> True if enabled, false otherwise. </returns>
|
||||
protected bool IsEnabled()
|
||||
{
|
||||
if (_backupConfig.Enabled)
|
||||
@@ -166,23 +162,21 @@ public class BackupService
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Generates the target directory path for the backup. The directory path is constructed using the `directory` from
|
||||
/// the configuration and the current backup date.
|
||||
/// </summary>
|
||||
/// <returns> The target directory path for the backup. </returns>
|
||||
protected string GenerateBackupTargetDir()
|
||||
{
|
||||
var backupDate = GenerateBackupDate();
|
||||
return Path.GetFullPath($"{_backupConfig.Directory}/{backupDate}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`.
|
||||
*
|
||||
* @returns The formatted backup date string.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Generates a formatted backup date string in the format `YYYY-MM-DD_hh-mm-ss`.
|
||||
/// </summary>
|
||||
/// <returns> The formatted backup date string. </returns>
|
||||
protected string GenerateBackupDate()
|
||||
{
|
||||
var date = _timeUtil.GetDateTimeNow();
|
||||
@@ -190,14 +184,11 @@ public class BackupService
|
||||
return $"{date.Year}-{date.Month}-{date.Day}_{date.Hour}-{date.Minute}-{date.Second}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Cleans up old backups in the backup directory. <br/>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
protected void CleanBackups()
|
||||
{
|
||||
var backupDir = _backupConfig.Directory;
|
||||
@@ -230,12 +221,11 @@ public class BackupService
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 a List of sorted backup file paths.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Retrieves and sorts the backup file paths from the specified directory.
|
||||
/// </summary>
|
||||
/// <param name="dir"> The directory to search for backup files. </param>
|
||||
/// <returns> List of sorted backup file paths. </returns>
|
||||
private List<string> GetBackupPaths(string dir)
|
||||
{
|
||||
var backups = _fileUtil.GetDirectories(dir).ToList();
|
||||
@@ -244,13 +234,12 @@ public class BackupService
|
||||
return backups;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Compares two backup folder names based on their extracted dates.
|
||||
/// </summary>
|
||||
/// <param name="a"> The name of the first backup folder. </param>
|
||||
/// <param name="b"> The name of the second backup folder. </param>
|
||||
/// <returns> The difference in time between the two dates in milliseconds, or `null` if either date is invalid. </returns>
|
||||
private int CompareBackupDates(string a, string b)
|
||||
{
|
||||
var dateA = ExtractDateFromFolderName(a);
|
||||
@@ -264,12 +253,11 @@ public class BackupService
|
||||
return (int) (dateA.Value.ToFileTimeUtc() - dateB.Value.ToFileTimeUtc());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 DateTime object if the folder name is in the correct format, otherwise null.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Extracts a date from a folder name string formatted as `YYYY-MM-DD_hh-mm-ss`.
|
||||
/// </summary>
|
||||
/// <param name="folderName"> The name of the folder from which to extract the date. </param>
|
||||
/// <returns> A DateTime object if the folder name is in the correct format, otherwise null. </returns>
|
||||
private DateTime? ExtractDateFromFolderName(string folderName)
|
||||
{
|
||||
// backup
|
||||
@@ -290,12 +278,11 @@ public class BackupService
|
||||
return new DateTime(year, month, day, hour, minute, second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes excess backups from the backup directory.
|
||||
*
|
||||
* @param backups - A List of backup file names to be removed.
|
||||
* @returns A promise that resolves when all specified backups have been removed.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Removes excess backups from the backup directory.
|
||||
/// </summary>
|
||||
/// <param name="backupFilenames"> List of backup file names to be removed. </param>
|
||||
/// <returns> A promise that resolves when all specified backups have been removed. </returns>
|
||||
private void RemoveExcessBackups(List<string> backupFilenames)
|
||||
{
|
||||
var filePathsToDelete = backupFilenames.Select(x => x);
|
||||
@@ -310,11 +297,10 @@ public class BackupService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a List of active server mod details.
|
||||
*
|
||||
* @returns A List of mod names.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get a List of active server mod details.
|
||||
/// </summary>
|
||||
/// <returns> A List of mod names. </returns>
|
||||
protected List<string> GetActiveServerMods()
|
||||
{
|
||||
var mods = _applicationContext?.GetLatestValue(ContextVariableType.LOADED_MOD_ASSEMBLIES)?.GetValue<List<SptMod>>();
|
||||
|
||||
@@ -44,10 +44,11 @@ public class BotEquipmentModPoolService
|
||||
_gearModPool = new ConcurrentDictionary<string, ConcurrentDictionary<string, HashSet<string>>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store dictionary of mods for each item passed in
|
||||
* @param items items to find related mods and store in modPool
|
||||
*/
|
||||
/// <summary>
|
||||
/// Store dictionary of mods for each item passed in
|
||||
/// </summary>
|
||||
/// <param name="items"> Items to find related mods and store in modPool </param>
|
||||
/// <param name="poolType"> Mod pool to choose from e.g. "weapon" for weaponModPool </param>
|
||||
protected void GeneratePool(IEnumerable<TemplateItem>? items, string poolType)
|
||||
{
|
||||
if (items is null)
|
||||
@@ -143,20 +144,20 @@ public class BotEquipmentModPoolService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the mod pool
|
||||
*/
|
||||
/// <summary>
|
||||
/// Empty the mod pool
|
||||
/// </summary>
|
||||
public void ResetPool()
|
||||
{
|
||||
_weaponModPool.Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of compatible mods for an items mod slot (generate pool if it doesn't exist already)
|
||||
* @param itemTpl item to look up
|
||||
* @param slotName slot to get compatible mods for
|
||||
* @returns tpls that fit the slot
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get array of compatible mods for an items mod slot (generate pool if it doesn't exist already)
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> Item to look up </param>
|
||||
/// <param name="slotName"> Slot to get compatible mods for </param>
|
||||
/// <returns> Hashset of tpls that fit the slot </returns>
|
||||
public HashSet<string> GetCompatibleModsForWeaponSlot(string itemTpl, string slotName)
|
||||
{
|
||||
if (!_weaponPoolGenerated)
|
||||
@@ -168,11 +169,11 @@ public class BotEquipmentModPoolService
|
||||
return _weaponModPool[itemTpl][slotName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mods for a piece of gear by its tpl
|
||||
* @param itemTpl items tpl to look up mods for
|
||||
* @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get mods for a piece of gear by its tpl
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> Items tpl to look up mods for </param>
|
||||
/// <returns> Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value </returns>
|
||||
public ConcurrentDictionary<string, HashSet<string>> GetModsForGearSlot(string itemTpl)
|
||||
{
|
||||
if (!_armorPoolGenerated)
|
||||
@@ -185,11 +186,11 @@ public class BotEquipmentModPoolService
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mods for a weapon by its tpl
|
||||
* @param itemTpl Weapons tpl to look up mods for
|
||||
* @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get mods for a weapon by its tpl
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> Weapons tpl to look up mods for </param>
|
||||
/// <returns> Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value </returns>
|
||||
public ConcurrentDictionary<string, HashSet<string>> GetModsForWeaponSlot(string itemTpl)
|
||||
{
|
||||
if (!_weaponPoolGenerated)
|
||||
@@ -200,6 +201,11 @@ public class BotEquipmentModPoolService
|
||||
return _weaponModPool[itemTpl];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get required mods for a weapon by its tpl
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> Weapons tpl to look up mods for </param>
|
||||
/// <returns> Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value </returns>
|
||||
public Dictionary<string, HashSet<string>>? GetRequiredModsForWeaponSlot(string itemTpl)
|
||||
{
|
||||
var result = new Dictionary<string, HashSet<string>>();
|
||||
@@ -225,9 +231,9 @@ public class BotEquipmentModPoolService
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create weapon mod pool and set generated flag to true
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create weapon mod pool and set generated flag to true
|
||||
/// </summary>
|
||||
protected void GenerateWeaponPool()
|
||||
{
|
||||
var weapons = _databaseService.GetItems()
|
||||
@@ -240,9 +246,9 @@ public class BotEquipmentModPoolService
|
||||
_weaponPoolGenerated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create gear mod pool and set generated flag to true
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create gear mod pool and set generated flag to true
|
||||
/// </summary>
|
||||
protected void GenerateGearPool()
|
||||
{
|
||||
var gear = _databaseService.GetItems()
|
||||
|
||||
@@ -16,10 +16,11 @@ public class BotGenerationCacheService(
|
||||
protected ConcurrentDictionary<string, List<BotBase>> _storedBots = new();
|
||||
|
||||
|
||||
/**
|
||||
* Store list of bots in cache, shuffle results before storage
|
||||
* @param botsToStore Bots we want to store in the cache
|
||||
*/
|
||||
/// <summary>
|
||||
/// Store list of bots in cache, shuffle results before storage
|
||||
/// </summary>
|
||||
/// <param name="key"> Role bot is stored as (assault/bossTagilla etc.) </param>
|
||||
/// <param name="botsToStore"> Bots we want to store in the cache </param>
|
||||
public void StoreBots(string key, List<BotBase> botsToStore)
|
||||
{
|
||||
foreach (var bot in botsToStore)
|
||||
@@ -31,12 +32,12 @@ public class BotGenerationCacheService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return a bot based on its role
|
||||
* Remove bot from internal list so it can't be retrieved again
|
||||
* @param key role to retrieve (assault/bossTagilla etc)
|
||||
* @returns BotBase object
|
||||
*/
|
||||
/// <summary>
|
||||
/// Find and return a bot based on its role. <br/>
|
||||
/// Remove bot from internal list so it can't be retrieved again.
|
||||
/// </summary>
|
||||
/// <param name="key"> role to retrieve (assault/bossTagilla etc) </param>
|
||||
/// <returns> BotBase object </returns>
|
||||
public BotBase? GetBot(string key)
|
||||
{
|
||||
if (_storedBots.TryGetValue(key, out var bots))
|
||||
@@ -62,39 +63,39 @@ public class BotGenerationCacheService(
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache a bot that has been sent to the client in memory for later use post-raid to determine if player killed a traitor scav
|
||||
* @param botToStore Bot object to store
|
||||
*/
|
||||
/// <summary>
|
||||
/// Cache a bot that has been sent to the client in memory for later use post-raid to determine if player killed a traitor scav
|
||||
/// </summary>
|
||||
/// <param name="botToStore"> Bot object to store </param>
|
||||
public void StoreUsedBot(BotBase botToStore)
|
||||
{
|
||||
_activeBotsInRaid.Enqueue(botToStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a bot by its profileId that has been generated and sent to client for current raid
|
||||
* Cache is wiped post-raid in client/match/offline/end endOfflineRaid()
|
||||
* @param profileId Id of bot to get
|
||||
* @returns BotBase
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get a bot by its profileId that has been generated and sent to client for current raid. <br/>
|
||||
/// Cache is wiped post-raid in client/match/offline/end endOfflineRaid()
|
||||
/// </summary>
|
||||
/// <param name="profileId"> ID of bot to get </param>
|
||||
/// <returns> BotBase object </returns>
|
||||
public BotBase? GetUsedBot(string profileId)
|
||||
{
|
||||
return _activeBotsInRaid.FirstOrDefault(x => x.Id == profileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all cached bot profiles from memory
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove all cached bot profiles from memory
|
||||
/// </summary>
|
||||
public void ClearStoredBots()
|
||||
{
|
||||
_storedBots.Clear();
|
||||
_activeBotsInRaid = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Does cache have a bot with requested key
|
||||
* @returns false if empty
|
||||
*/
|
||||
/// <summary>
|
||||
/// Does cache have a bot with requested key
|
||||
/// </summary>
|
||||
/// <returns> False if empty </returns>
|
||||
public bool CacheHasBotWithKey(string key, int size = 0)
|
||||
{
|
||||
return _storedBots.ContainsKey(key) && _storedBots[key].Count > size;
|
||||
|
||||
@@ -56,10 +56,10 @@ public class BotWeaponModLimitService(
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if weapon mod item is on limited list + has surpassed the limit set for it
|
||||
/// Exception: Always allow ncstar backup mount
|
||||
/// Exception: Always allow scopes with a scope for a parent
|
||||
/// Exception: Always disallow mounts that hold only scopes once scope limit reached
|
||||
/// Check if weapon mod item is on limited list + has surpassed the limit set for it <br/>
|
||||
/// Exception: Always allow ncstar backup mount <br/>
|
||||
/// Exception: Always allow scopes with a scope for a parent <br/>
|
||||
/// Exception: Always disallow mounts that hold only scopes once scope limit reached <br/>
|
||||
/// Exception: Always disallow mounts that hold only flashlights once flashlight limit reached
|
||||
/// </summary>
|
||||
/// <param name="botRole">role the bot has e.g. assault</param>
|
||||
|
||||
@@ -123,7 +123,12 @@ public class CircleOfCultistService(
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the reward amount multiple value based on players hideout management skill + configs rewardPriceMultiplerMinMax values
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <param name="cultistCircleSettings"> Circle config settings </param>
|
||||
/// <returns> Reward Amount Multiplier </returns>
|
||||
private double GetRewardAmountMultiplier(PmcData pmcData, CultistCircleSettings cultistCircleSettings)
|
||||
{
|
||||
// Get a randomised value to multiply the sacrificed rouble cost by
|
||||
|
||||
@@ -215,10 +215,10 @@ public class CreateProfileService(
|
||||
return pmcData.Id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a profile
|
||||
* @param sessionID Id of profile to delete
|
||||
*/
|
||||
/// <summary>
|
||||
/// Delete a profile
|
||||
/// </summary>
|
||||
/// <param name="sessionID"> ID of profile to delete </param>
|
||||
protected void DeleteProfileBySessionId(string sessionID)
|
||||
{
|
||||
if (_saveServer.GetProfiles().ContainsKey(sessionID))
|
||||
@@ -233,10 +233,10 @@ public class CreateProfileService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* make profiles pmcData.Inventory.equipment unique
|
||||
* @param pmcData Profile to update
|
||||
*/
|
||||
/// <summary>
|
||||
/// Make profiles pmcData.Inventory.equipment unique
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Profile to update </param>
|
||||
protected void UpdateInventoryEquipmentId(PmcData pmcData)
|
||||
{
|
||||
var oldEquipmentId = pmcData.Inventory.Equipment;
|
||||
@@ -257,10 +257,10 @@ public class CreateProfileService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For each trader reset their state to what a level 1 player would see
|
||||
* @param sessionId Session id of profile to reset
|
||||
*/
|
||||
/// <summary>
|
||||
/// For each trader reset their state to what a level 1 player would see
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID of profile to reset </param>
|
||||
protected void ResetAllTradersInProfile(string sessionId)
|
||||
{
|
||||
foreach (var traderId in _databaseService.GetTraders().Keys)
|
||||
@@ -269,11 +269,11 @@ public class CreateProfileService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a profile has the necessary internal containers e.g. questRaidItems / sortingTable
|
||||
* DOES NOT check that stash exists
|
||||
* @param pmcData Profile to check
|
||||
*/
|
||||
/// <summary>
|
||||
/// Ensure a profile has the necessary internal containers e.g. questRaidItems / sortingTable <br/>
|
||||
/// DOES NOT check that stash exists
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Profile to check </param>
|
||||
protected void AddMissingInternalContainersToProfile(PmcData pmcData)
|
||||
{
|
||||
if (!pmcData.Inventory.Items.Any(item => item.Id == pmcData.Inventory.HideoutCustomizationStashId))
|
||||
@@ -462,9 +462,9 @@ public class CreateProfileService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game edition of a profile chosen on creation in Launcher
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the game edition of a profile chosen on creation in Launcher
|
||||
/// </summary>
|
||||
private string? GetGameEdition(SptProfile profile)
|
||||
{
|
||||
var edition = profile.CharacterData?.PmcData?.Info?.GameVersion;
|
||||
@@ -486,13 +486,13 @@ public class CreateProfileService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all quests in player profile, inspect rewards for the quests current state (accepted/completed)
|
||||
* and send rewards to them in mail
|
||||
* @param profileDetails Player profile
|
||||
* @param sessionID Session id
|
||||
* @param response Event router response
|
||||
*/
|
||||
/// <summary>
|
||||
/// Iterate over all quests in player profile, inspect rewards for the quests current state (accepted/completed)
|
||||
/// and send rewards to them in mail
|
||||
/// </summary>
|
||||
/// <param name="profileDetails"> Player profile </param>
|
||||
/// <param name="sessionID"> Session ID </param>
|
||||
/// <param name="response"> Event router response </param>
|
||||
protected void GivePlayerStartingQuestRewards(
|
||||
SptProfile profileDetails,
|
||||
string sessionID,
|
||||
|
||||
@@ -14,7 +14,7 @@ public class CustomLocaleService(
|
||||
|
||||
/// <summary>
|
||||
/// Path should link to a folder containing every locale that should be added to the server locales
|
||||
/// e.g. en.json for english, fr.json for french
|
||||
/// e.g. en.json for english, fr.json for french. <br/>
|
||||
/// Inside each JSON should be a Dictionary of the locale key and localised text
|
||||
/// </summary>
|
||||
/// <param name="locale">en/fr/de</param>
|
||||
@@ -27,7 +27,7 @@ public class CustomLocaleService(
|
||||
|
||||
/// <summary>
|
||||
/// Path should link to a folder containing every locale that should be added to the game locales
|
||||
/// e.g. en.json for english, fr.json for french
|
||||
/// e.g. en.json for english, fr.json for french. <br/>
|
||||
/// Inside each JSON should be a Dictionary of the locale key and localised text
|
||||
/// </summary>
|
||||
/// <param name="locale">en/fr/de</param>
|
||||
|
||||
@@ -25,17 +25,13 @@ public class DatabaseService(
|
||||
{
|
||||
protected bool isDataValid = true;
|
||||
|
||||
/**
|
||||
* @returns assets/database/
|
||||
*/
|
||||
/// <returns> assets/database/ </returns>
|
||||
public DatabaseTables GetTables()
|
||||
{
|
||||
return _databaseServer.GetTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/bots/
|
||||
*/
|
||||
/// <returns> assets/database/bots/ </returns>
|
||||
public Bots GetBots()
|
||||
{
|
||||
if (_databaseServer.GetTables().Bots == null)
|
||||
@@ -46,9 +42,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Bots!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/globals.json
|
||||
*/
|
||||
/// <returns> assets/database/globals.json </returns>
|
||||
public Globals GetGlobals()
|
||||
{
|
||||
if (_databaseServer.GetTables().Globals == null)
|
||||
@@ -64,9 +58,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Globals!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/hideout/
|
||||
*/
|
||||
/// <returns> assets/database/hideout/ </returns>
|
||||
public Hideout GetHideout()
|
||||
{
|
||||
if (_databaseServer.GetTables().Hideout == null)
|
||||
@@ -79,9 +71,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Hideout!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/locales/
|
||||
*/
|
||||
/// <returns> assets/database/locales/ </returns>
|
||||
public LocaleBase GetLocales()
|
||||
{
|
||||
if (_databaseServer.GetTables().Locales == null)
|
||||
@@ -94,9 +84,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Locales!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/locations
|
||||
*/
|
||||
/// <returns> assets/database/locations </returns>
|
||||
public Locations GetLocations()
|
||||
{
|
||||
if (_databaseServer.GetTables().Locations == null)
|
||||
@@ -109,11 +97,11 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Locations!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specific location by its Id
|
||||
* @param locationId Desired location id
|
||||
* @returns assets/database/locations/
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get specific location by its ID
|
||||
/// </summary>
|
||||
/// <param name="locationId"> Desired location ID </param>
|
||||
/// <returns> assets/database/locations/ </returns>
|
||||
public Location GetLocation(string locationId)
|
||||
{
|
||||
var locations = GetLocations();
|
||||
@@ -126,9 +114,7 @@ public class DatabaseService(
|
||||
return desiredLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/match/
|
||||
*/
|
||||
/// <returns> assets/database/match/ </returns>
|
||||
public Match GetMatch()
|
||||
{
|
||||
if (_databaseServer.GetTables().Match == null)
|
||||
@@ -141,9 +127,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Match!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/server.json
|
||||
*/
|
||||
/// <returns> assets/database/server.json </returns>
|
||||
public ServerBase GetServer()
|
||||
{
|
||||
if (_databaseServer.GetTables().Server == null)
|
||||
@@ -159,9 +143,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Server!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/settings.json
|
||||
*/
|
||||
/// <returns> assets/database/settings.json </returns>
|
||||
public SettingsBase GetSettings()
|
||||
{
|
||||
if (_databaseServer.GetTables().Settings == null)
|
||||
@@ -177,9 +159,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Settings!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/
|
||||
*/
|
||||
/// <returns> assets/database/templates/ </returns>
|
||||
public Templates GetTemplates()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates == null)
|
||||
@@ -195,9 +175,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/achievements.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/achievements.json </returns>
|
||||
public List<Achievement> GetAchievements()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Achievements == null)
|
||||
@@ -213,9 +191,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Achievements!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/customisation.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/customisation.json </returns>
|
||||
public Dictionary<string, CustomizationItem?> GetCustomization()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Customization == null)
|
||||
@@ -231,9 +207,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Customization!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/handbook.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/handbook.json </returns>
|
||||
public HandbookBase GetHandbook()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Handbook == null)
|
||||
@@ -244,9 +218,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Handbook!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/items.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/items.json </returns>
|
||||
public Dictionary<string, TemplateItem> GetItems()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Items == null)
|
||||
@@ -257,9 +229,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Items!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/prices.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/prices.json </returns>
|
||||
public Dictionary<string, double> GetPrices()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Prices == null)
|
||||
@@ -270,9 +240,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Prices!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/profiles.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/profiles.json </returns>
|
||||
public ProfileTemplates GetProfiles()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Profiles == null)
|
||||
@@ -283,9 +251,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Profiles!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/templates/quests.json
|
||||
*/
|
||||
/// <returns> assets/database/templates/quests.json </returns>
|
||||
public Dictionary<string, Quest> GetQuests()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.Quests == null)
|
||||
@@ -296,9 +262,7 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.Quests!;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/traders/
|
||||
*/
|
||||
/// <returns> assets/database/traders/ </returns>
|
||||
public Dictionary<string, Trader> GetTraders()
|
||||
{
|
||||
if (_databaseServer.GetTables().Traders == null)
|
||||
@@ -309,11 +273,11 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Traders!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specific trader by their Id
|
||||
* @param traderId Desired trader id
|
||||
* @returns assets/database/traders/
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get specific trader by their ID
|
||||
/// </summary>
|
||||
/// <param name="traderId"> Desired trader ID </param>
|
||||
/// <returns> assets/database/traders/ </returns>
|
||||
public Trader GetTrader(string traderId)
|
||||
{
|
||||
var traders = GetTraders();
|
||||
@@ -325,9 +289,7 @@ public class DatabaseService(
|
||||
return desiredTrader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns assets/database/locationServices/
|
||||
*/
|
||||
/// <returns> assets/database/locationServices/ </returns>
|
||||
public LocationServices GetLocationServices()
|
||||
{
|
||||
if (_databaseServer.GetTables().Templates?.LocationServices == null)
|
||||
@@ -338,9 +300,9 @@ public class DatabaseService(
|
||||
return _databaseServer.GetTables().Templates?.LocationServices!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the database doesn't contain invalid ID data
|
||||
*/
|
||||
/// <summary>
|
||||
/// Validates that the database doesn't contain invalid ID data
|
||||
/// </summary>
|
||||
public void ValidateDatabase()
|
||||
{
|
||||
var start = Stopwatch.StartNew();
|
||||
@@ -363,12 +325,12 @@ public class DatabaseService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the given table only contains valid MongoIDs
|
||||
* @param table Table to validate for MongoIDs
|
||||
* @param tableType The type of table, used in output message
|
||||
* @returns True if the table only contains valid data
|
||||
*/
|
||||
/// <summary>
|
||||
/// Validate that the given table only contains valid MongoIDs
|
||||
/// </summary>
|
||||
/// <param name="table"> Table to validate for MongoIDs</param>
|
||||
/// <param name="tableType"> The type of table, used in output message </param>
|
||||
/// <returns> True if the table only contains valid data </returns>
|
||||
private bool ValidateTable<T>(Dictionary<string, T> table, string tableType)
|
||||
{
|
||||
foreach (var keyValuePair in table)
|
||||
@@ -383,10 +345,10 @@ public class DatabaseService(
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the database is valid
|
||||
* @returns True if the database contains valid data, false otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if the database is valid
|
||||
/// </summary>
|
||||
/// <returns> True if the database contains valid data, false otherwise </returns>
|
||||
public bool IsDatabaseValid()
|
||||
{
|
||||
return isDataValid;
|
||||
|
||||
@@ -28,19 +28,19 @@ public class FenceService(
|
||||
ICloner _cloner
|
||||
)
|
||||
{
|
||||
/**
|
||||
* Desired baseline counts - Hydrated on initial assort generation as part of generateFenceAssorts()
|
||||
*/
|
||||
/// <summary>
|
||||
/// Desired baseline counts - Hydrated on initial assort generation as part of generateFenceAssorts()
|
||||
/// </summary>
|
||||
protected FenceAssortGenerationValues desiredAssortCounts;
|
||||
|
||||
/**
|
||||
* Main assorts you see at all rep levels
|
||||
*/
|
||||
/// <summary>
|
||||
/// Main assorts you see at all rep levels
|
||||
/// </summary>
|
||||
protected TraderAssort? fenceAssort;
|
||||
|
||||
/**
|
||||
* Assorts shown on a separate tab when you max out fence rep
|
||||
*/
|
||||
/// <summary>
|
||||
/// Assorts shown on a separate tab when you max out fence rep
|
||||
/// </summary>
|
||||
protected TraderAssort? fenceDiscountAssort;
|
||||
|
||||
protected HashSet<string> fenceItemUpdCompareProperties =
|
||||
@@ -56,65 +56,57 @@ public class FenceService(
|
||||
"RepairKit"
|
||||
];
|
||||
|
||||
/**
|
||||
* Time when some items in assort will be replaced
|
||||
*/
|
||||
/// <summary>
|
||||
/// Time when some items in assort will be replaced
|
||||
/// </summary>
|
||||
protected long nextPartialRefreshTimestamp;
|
||||
|
||||
protected TraderConfig traderConfig = configServer.GetConfig<TraderConfig>();
|
||||
|
||||
|
||||
/**
|
||||
* Replace main fence assort with new assort
|
||||
* @param assort New assorts to replace old with
|
||||
*/
|
||||
/// <summary>
|
||||
/// Replace main fence assort with new assort
|
||||
/// </summary>
|
||||
/// <param name="assort"> New assorts to replace old with </param>
|
||||
public void SetFenceAssort(TraderAssort assort)
|
||||
{
|
||||
fenceAssort = assort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace discount fence assort with new assort
|
||||
* @param assort New assorts to replace old with
|
||||
*/
|
||||
public void SetDiscountFenceAssort(TraderAssort assort)
|
||||
{
|
||||
fenceDiscountAssort = assort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get main fence assort
|
||||
* @return ITraderAssort
|
||||
*/
|
||||
public TraderAssort? GetMainFenceAssort()
|
||||
{
|
||||
return fenceAssort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get discount fence assort
|
||||
* @return ITraderAssort
|
||||
*/
|
||||
public TraderAssort? GetDiscountFenceAssort()
|
||||
{
|
||||
return fenceDiscountAssort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace high rep level fence assort with new assort
|
||||
* @param discountAssort New assorts to replace old with
|
||||
*/
|
||||
/// <summary>
|
||||
/// Replace discount fence assort with new assort
|
||||
/// </summary>
|
||||
/// <param name="discountAssort"> New assorts to replace old with </param>
|
||||
public void SetFenceDiscountAssort(TraderAssort discountAssort)
|
||||
{
|
||||
fenceDiscountAssort = discountAssort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assorts player can purchase
|
||||
* Adjust prices based on fence level of player
|
||||
* @param pmcProfile Player profile
|
||||
* @returns ITraderAssort
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get main fence assort
|
||||
/// </summary>
|
||||
/// <returns> TraderAssort </returns>
|
||||
public TraderAssort? GetMainFenceAssort()
|
||||
{
|
||||
return fenceAssort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get discount fence assort
|
||||
/// </summary>
|
||||
/// <returns> TraderAssort </returns>
|
||||
/// @return ITraderAssort
|
||||
public TraderAssort? GetDiscountFenceAssort()
|
||||
{
|
||||
return fenceDiscountAssort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get assorts player can purchase <br/>
|
||||
/// Adjust prices based on fence level of player
|
||||
/// </summary>
|
||||
/// <param name="pmcProfile"> Player profile </param>
|
||||
/// <returns> TraderAssort </returns>
|
||||
public TraderAssort GetFenceAssorts(PmcData pmcProfile)
|
||||
{
|
||||
if (traderConfig.Fence.RegenerateAssortsOnRefresh)
|
||||
@@ -144,11 +136,11 @@ public class FenceService(
|
||||
return assort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to fence assort a single item (with its children)
|
||||
* @param items the items to add with all its childrens
|
||||
* @param mainItem the most parent item of the array
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adds to fence assort a single item (with its children)
|
||||
/// </summary>
|
||||
/// <param name="items"> The items to add with all its children </param>
|
||||
/// <param name="mainItem"> The most parent item of the array </param>
|
||||
public void AddItemsToFenceAssort(List<Item> items, Item mainItem)
|
||||
{
|
||||
// HUGE THANKS TO LACYWAY AND LEAVES FOR PROVIDING THIS SOLUTION FOR SPT TO IMPLEMENT!!
|
||||
@@ -192,12 +184,12 @@ public class FenceService(
|
||||
UpdateFenceAssorts(createAssort, fenceAssort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the overall price for an item (with all its children)
|
||||
* @param itemTpl the item tpl to calculate the fence price for
|
||||
* @param items the items (with its children) to calculate fence price for
|
||||
* @returns the fence price of the item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Calculates the overall price for an item (with all its children)
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> The item tpl to calculate the fence price for </param>
|
||||
/// <param name="items"> The items (with its children) to calculate fence price for </param>
|
||||
/// <returns> Price of the item for Fence </returns>
|
||||
public double? GetItemPrice(string itemTpl, List<Item> items)
|
||||
{
|
||||
return itemHelper.IsOfBaseclass(itemTpl, BaseClasses.AMMO_BOX)
|
||||
@@ -205,12 +197,12 @@ public class FenceService(
|
||||
: handbookHelper.GetTemplatePrice(itemTpl) * traderConfig.Fence.ItemPriceMult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the overall price for an ammo box, where only one item is
|
||||
* the ammo box itself and every other items are the bullets in that box
|
||||
* @param items the ammo box (and all its children ammo items)
|
||||
* @returns the price of the ammo box
|
||||
*/
|
||||
/// <summary>
|
||||
/// Calculate the overall price for an ammo box, where only one item is
|
||||
/// the ammo box itself and every other items are the bullets in that box
|
||||
/// </summary>
|
||||
/// <param name="items"> The ammo box (and all its children ammo items) </param>
|
||||
/// <returns> The price of the ammo box </returns>
|
||||
protected double? GetAmmoBoxPrice(List<Item> items)
|
||||
{
|
||||
double? total = 0D;
|
||||
@@ -225,12 +217,12 @@ public class FenceService(
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust all items contained inside an assort by a multiplier
|
||||
* @param assort (clone)Assort that contains items with prices to adjust
|
||||
* @param itemMultiplier multiplier to use on items
|
||||
* @param presetMultiplier preset multiplier to use on presets
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adjust all items contained inside an assort by a multiplier
|
||||
/// </summary>
|
||||
/// <param name="assort"> (clone) Assort that contains items with prices to adjust </param>
|
||||
/// <param name="itemMultiplier"> Multiplier to use on items </param>
|
||||
/// <param name="presetMultiplier"> Multiplier to use on presets </param>
|
||||
protected void AdjustAssortItemPricesByConfigMultiplier(
|
||||
TraderAssort assort,
|
||||
double itemMultiplier,
|
||||
@@ -244,12 +236,13 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two trader assort files together
|
||||
* @param firstAssort assort 1#
|
||||
* @param secondAssort assort #2
|
||||
* @returns merged assort
|
||||
*/
|
||||
/// <summary>
|
||||
/// Merge two trader assort files together
|
||||
/// </summary>
|
||||
/// <param name="firstAssort"> Assort #1 </param>
|
||||
/// <param name="secondAssort"> Assort #2 </param>
|
||||
/// <returns> Merged assort </returns>
|
||||
// TODO: can be moved to a helper?
|
||||
protected TraderAssort MergeAssorts(TraderAssort firstAssort, TraderAssort secondAssort)
|
||||
{
|
||||
foreach (var itemId in secondAssort.BarterScheme.Keys)
|
||||
@@ -270,13 +263,13 @@ public class FenceService(
|
||||
return firstAssort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust assorts price by a modifier
|
||||
* @param item assort item details
|
||||
* @param assort assort to be modified
|
||||
* @param modifier value to multiply item price by
|
||||
* @param presetModifier value to multiply preset price by
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adjust assorts price by a modifier
|
||||
/// </summary>
|
||||
/// <param name="item"> Assort item details</param>
|
||||
/// <param name="assort"> Assort to be modified </param>
|
||||
/// <param name="modifier"> Value to multiply item price by </param>
|
||||
/// <param name="presetModifier"> Value to multiply preset price by </param>
|
||||
protected void AdjustItemPriceByModifier(
|
||||
Item item,
|
||||
TraderAssort assort,
|
||||
@@ -313,27 +306,27 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fence assorts with no price adjustments based on fence rep
|
||||
* @returns ITraderAssort
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get fence assorts with no price adjustments based on fence rep
|
||||
/// </summary>
|
||||
/// <returns> TraderAssort </returns>
|
||||
public TraderAssort GetRawFenceAssorts()
|
||||
{
|
||||
return MergeAssorts(_cloner.Clone(fenceAssort), _cloner.Clone(fenceDiscountAssort));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does fence need to perform a partial refresh because its passed the refresh timer defined in trader.json
|
||||
* @returns true if it needs a partial refresh
|
||||
*/
|
||||
/// <summary>
|
||||
/// Does fence need to perform a partial refresh because its passed the refresh timer defined in trader.json
|
||||
/// </summary>
|
||||
/// <returns> True if it needs a partial refresh </returns>
|
||||
public bool NeedsPartialRefresh()
|
||||
{
|
||||
return timeUtil.GetTimeStamp() > nextPartialRefreshTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a percentage of fence assorts with freshly generated items
|
||||
*/
|
||||
/// <summary>
|
||||
/// Replace a percentage of fence assorts with freshly generated items
|
||||
/// </summary>
|
||||
public void PerformPartialRefresh()
|
||||
{
|
||||
var itemCountToReplace = GetCountOfItemsToReplace(traderConfig.Fence.AssortSize);
|
||||
@@ -391,11 +384,11 @@ public class FenceService(
|
||||
IncrementPartialRefreshTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the process of folding new assorts into existing assorts, when a new assort exists already, increment its StackObjectsCount instead
|
||||
* @param newFenceAssorts Assorts to fold into existing fence assorts
|
||||
* @param existingFenceAssorts Current fence assorts new assorts will be added to
|
||||
*/
|
||||
/// <summary>
|
||||
/// Handle the process of folding new assorts into existing assorts, when a new assort exists already, increment its StackObjectsCount instead
|
||||
/// </summary>
|
||||
/// <param name="newFenceAssorts"> Assorts to fold into existing fence assorts </param>
|
||||
/// <param name="existingFenceAssorts"> Current fence assorts, new assorts will be added to </param>
|
||||
protected void UpdateFenceAssorts(
|
||||
CreateFenceAssortsResult newFenceAssorts,
|
||||
TraderAssort existingFenceAssorts
|
||||
@@ -454,20 +447,20 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment fence next refresh timestamp by current timestamp + partialRefreshTimeSeconds from config
|
||||
*/
|
||||
/// <summary>
|
||||
/// Increment fence next refresh timestamp by current timestamp + partialRefreshTimeSeconds from config
|
||||
/// </summary>
|
||||
protected void IncrementPartialRefreshTime()
|
||||
{
|
||||
nextPartialRefreshTimestamp = timeUtil.GetTimeStamp() + traderConfig.Fence.PartialRefreshTimeSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get values that will hydrate the passed in assorts back to the desired counts
|
||||
* @param assortItems Current assorts after items have been removed
|
||||
* @param generationValues Base counts assorts should be adjusted to
|
||||
* @returns IGenerationAssortValues object with adjustments needed to reach desired state
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get values that will hydrate the passed in assorts back to the desired counts
|
||||
/// </summary>
|
||||
/// <param name="assortItems"> Current assorts after items have been removed </param>
|
||||
/// <param name="generationValues"> Base counts assorts should be adjusted to </param>
|
||||
/// <returns> GenerationAssortValues object with adjustments needed to reach desired state </returns>
|
||||
protected GenerationAssortValues GetItemCountsToGenerate(
|
||||
List<Item> assortItems,
|
||||
GenerationAssortValues generationValues
|
||||
@@ -507,11 +500,11 @@ public class FenceService(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete desired number of items from assort (including children)
|
||||
* @param itemCountToReplace
|
||||
* @param discountItemCountToReplace
|
||||
*/
|
||||
/// <summary>
|
||||
/// Delete desired number of items from assort (including children)
|
||||
/// </summary>
|
||||
/// <param name="itemCountToReplace"> Number of items to replace </param>
|
||||
/// <param name="assort"> Assort to adjust </param>
|
||||
protected void DeleteRandomAssorts(int itemCountToReplace, TraderAssort assort)
|
||||
{
|
||||
if (assort?.Items?.Count > 0)
|
||||
@@ -524,11 +517,11 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose an item at random and remove it + mods from assorts
|
||||
* @param assort Trader assort to remove item from
|
||||
* @param rootItems Pool of root items to pick from to remove
|
||||
*/
|
||||
/// <summary>
|
||||
/// Choose an item at random and remove it + mods from assorts
|
||||
/// </summary>
|
||||
/// <param name="assort"> Trader assort to remove item from </param>
|
||||
/// <param name="rootItems"> Pool of root items to pick from to remove </param>
|
||||
protected void RemoveRandomItemFromAssorts(TraderAssort assort, List<Item> rootItems)
|
||||
{
|
||||
// Pick a random root item to remove from Fence
|
||||
@@ -573,20 +566,20 @@ public class FenceService(
|
||||
assort.LoyalLevelItems.Remove(rootItemToAdjust.Id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an integer rounded count of items to replace based on percentrage from traderConfig value
|
||||
* @param totalItemCount total item count
|
||||
* @returns rounded int of items to replace
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get an integer rounded count of items to replace based on percentage from traderConfig value
|
||||
/// </summary>
|
||||
/// <param name="totalItemCount"> Total item count </param>
|
||||
/// <returns> Rounded int of items to replace </returns>
|
||||
protected int GetCountOfItemsToReplace(int totalItemCount)
|
||||
{
|
||||
return (int) Math.Round(totalItemCount * (traderConfig.Fence.PartialRefreshChangePercent / 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of items fence offers
|
||||
* @returns number
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the count of items fence offers
|
||||
/// </summary>
|
||||
/// <returns> Number </returns>
|
||||
public int GetOfferCount()
|
||||
{
|
||||
if ((fenceAssort?.Items?.Count ?? 0) == 0)
|
||||
@@ -597,10 +590,10 @@ public class FenceService(
|
||||
return fenceAssort.Items.Count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create trader assorts for fence and store in fenceService cache
|
||||
* Uses fence base cache generatedon server start as a base
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create trader assorts for fence and store in fenceService cache
|
||||
/// Uses fence base cache generation server start as a base
|
||||
/// </summary>
|
||||
public void GenerateFenceAssorts()
|
||||
{
|
||||
// Reset refresh time now assorts are being generated
|
||||
@@ -622,11 +615,11 @@ public class FenceService(
|
||||
SetFenceDiscountAssort(ConvertIntoFenceAssort(discountAssorts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the intermediary assort data generated into format client can process
|
||||
* @param intermediaryAssorts Generated assorts that will be converted
|
||||
* @returns ITraderAssort
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert the intermediary assort data generated into format client can process
|
||||
/// </summary>
|
||||
/// <param name="intermediaryAssorts"> Generated assorts that will be converted </param>
|
||||
/// <returns> TraderAssort in the correct data format for Fence </returns>
|
||||
protected TraderAssort ConvertIntoFenceAssort(CreateFenceAssortsResult intermediaryAssorts)
|
||||
{
|
||||
var result = CreateFenceAssortSkeleton();
|
||||
@@ -641,10 +634,10 @@ public class FenceService(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object that contains calculated fence assort item values to make based on config
|
||||
* Stored in desiredAssortCounts
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create object that contains calculated fence assort item values to make based on config.
|
||||
/// Stored in desiredAssortCounts
|
||||
/// </summary>
|
||||
protected void CreateInitialFenceAssortGenerationValues()
|
||||
{
|
||||
var result = new FenceAssortGenerationValues
|
||||
@@ -690,10 +683,10 @@ public class FenceService(
|
||||
desiredAssortCounts = result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create skeleton to hold assort items
|
||||
* @returns ITraderAssort object
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create skeleton to hold assort items
|
||||
/// </summary>
|
||||
/// <returns> TraderAssort object </returns>
|
||||
protected TraderAssort CreateFenceAssortSkeleton()
|
||||
{
|
||||
return new TraderAssort
|
||||
@@ -705,11 +698,12 @@ public class FenceService(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate assorts parameter object with generated assorts
|
||||
* @param assortCount Number of assorts to generate
|
||||
* @param assorts object to add created assorts to
|
||||
*/
|
||||
/// <summary>
|
||||
/// Hydrate assorts parameter object with generated assorts
|
||||
/// </summary>
|
||||
/// <param name="itemCounts"> Number of items to generate per type (Item, WeaponPreset, EquipmentPreset) </param>
|
||||
/// <param name="loyaltyLevel"> Loyalty level to set new item to </param>
|
||||
/// <returns> CreateFenceAssortResult object </returns>
|
||||
protected CreateFenceAssortsResult CreateAssorts(GenerationAssortValues itemCounts, int loyaltyLevel)
|
||||
{
|
||||
var result = new CreateFenceAssortsResult
|
||||
@@ -742,14 +736,14 @@ public class FenceService(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add item assorts to existing assort data
|
||||
* @param assortCount Number to add
|
||||
* @param assorts Assorts data to add to
|
||||
* @param baseFenceAssortClone Base data to draw from
|
||||
* @param itemTypeLimits
|
||||
* @param loyaltyLevel Loyalty level to set new item to
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add item assorts to existing assort data
|
||||
/// </summary>
|
||||
/// <param name="assortCount"> Number to add </param>
|
||||
/// <param name="assorts"> Data to add to </param>
|
||||
/// <param name="baseFenceAssortClone"> Base data to draw from </param>
|
||||
/// <param name="itemTypeLimits"> Item limits per base class </param>
|
||||
/// <param name="loyaltyLevel"> Loyalty level to set new item to </param>
|
||||
protected void AddItemAssorts(
|
||||
int? assortCount,
|
||||
CreateFenceAssortsResult assorts,
|
||||
@@ -868,14 +862,14 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an assort item that matches the first parameter, also matches based on Upd properties
|
||||
* e.g. salewa hp resource units left
|
||||
* @param rootItemBeingAdded item to look for a match against
|
||||
* @param itemDbDetails Db details of matching item
|
||||
* @param itemsWithChildren Items to search through
|
||||
* @returns Matching assort item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Find an assort item that matches the first parameter, also matches based on Upd properties
|
||||
/// e.g. salewa hp resource units left
|
||||
/// </summary>
|
||||
/// <param name="rootItemBeingAdded"> item to look for a match against </param>
|
||||
/// <param name="itemDbDetails"> DB details of matching item </param>
|
||||
/// <param name="itemsWithChildren"> Items to search through </param>
|
||||
/// <returns> Matching assort item </returns>
|
||||
protected Item? GetMatchingItem(
|
||||
Item rootItemBeingAdded,
|
||||
TemplateItem itemDbDetails,
|
||||
@@ -946,12 +940,12 @@ public class FenceService(
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this item be forced into only 1 stack on fence
|
||||
* @param existingItem Existing item from fence assort
|
||||
* @param itemDbDetails Item we want to add db details
|
||||
* @returns True item should be force stacked
|
||||
*/
|
||||
/// <summary>
|
||||
/// Should this item be forced into only 1 stack on fence
|
||||
/// </summary>
|
||||
/// <param name="existingItem"> Existing item from fence assort </param>
|
||||
/// <param name="itemDbDetails"> Item we want to add DB details </param>
|
||||
/// <returns> True item should be force stacked </returns>
|
||||
protected bool ItemShouldBeForceStacked(Item? existingItem, TemplateItem itemDbDetails)
|
||||
{
|
||||
// No existing item in assort
|
||||
@@ -975,12 +969,12 @@ public class FenceService(
|
||||
return itemHelper.IsOfBaseclasses(tpl, traderConfig.Fence.PreventDuplicateOffersOfCategory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust price of item based on what is left to buy (resource/uses left)
|
||||
* @param barterSchemes All barter scheme for item having price adjusted
|
||||
* @param itemRoot Root item having price adjusted
|
||||
* @param itemTemplate Db template of item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adjust price of item based on what is left to buy (resource/uses left)
|
||||
/// </summary>
|
||||
/// <param name="barterSchemes"> All barter scheme for item having price adjusted </param>
|
||||
/// <param name="itemRoot"> Root item having price adjusted </param>
|
||||
/// <param name="itemTemplate"> DB template of item </param>
|
||||
protected void AdjustItemPriceByQuality(
|
||||
Dictionary<string, List<List<BarterScheme>>> barterSchemes,
|
||||
Item itemRoot,
|
||||
@@ -1033,13 +1027,14 @@ public class FenceService(
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find presets in base fence assort and add desired number to 'assorts' parameter
|
||||
* @param desiredWeaponPresetsCount
|
||||
* @param assorts Assorts to add preset to
|
||||
* @param baseFenceAssort Base data to draw from
|
||||
* @param loyaltyLevel Which loyalty level is required to see/buy item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Find presets in base fence assort and add desired number to 'assorts' parameter
|
||||
/// </summary>
|
||||
/// <param name="desiredWeaponPresetsCount"> How many WeaponPresets to add </param>
|
||||
/// <param name="desiredEquipmentPresetsCount"> How many WeaponPresets to add </param>
|
||||
/// <param name="assorts"> Assorts to add preset to </param>
|
||||
/// <param name="baseFenceAssort"> Base data to draw from </param>
|
||||
/// <param name="loyaltyLevel"> Loyalty level to set new presets to </param>
|
||||
protected void AddPresetsToAssort(
|
||||
int? desiredWeaponPresetsCount,
|
||||
int? desiredEquipmentPresetsCount,
|
||||
@@ -1178,11 +1173,11 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust plate / soft insert durability values
|
||||
* @param armor Armor item array to add mods into
|
||||
* @param itemDbDetails Armor items db template
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adjust plate / soft insert durability values
|
||||
/// </summary>
|
||||
/// <param name="armor"> Armor item array to add mods into </param>
|
||||
/// <param name="itemDbDetails"> Armor items db template </param>
|
||||
protected void RandomiseArmorModDurability(List<Item> armor, TemplateItem itemDbDetails)
|
||||
{
|
||||
// Armor has no mods, nothing to randomise
|
||||
@@ -1207,11 +1202,11 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomise the durability values of items on armor with a passed in slot
|
||||
* @param softInsertSlots Slots of items to randomise
|
||||
* @param armorItemAndMods Array of armor + inserts to get items from
|
||||
*/
|
||||
/// <summary>
|
||||
/// Randomise the durability values of items on armor with a passed in slot
|
||||
/// </summary>
|
||||
/// <param name="softInsertSlots"> Slots of items to randomise </param>
|
||||
/// <param name="armorItemAndMods"> Array of armor + inserts to get items from </param>
|
||||
protected void RandomiseArmorSoftInsertDurabilities(List<Slot> softInsertSlots, List<Item> armorItemAndMods)
|
||||
{
|
||||
foreach (var requiredSlot in softInsertSlots)
|
||||
@@ -1264,12 +1259,12 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomise the durability values of plate items in armor
|
||||
* Has chance to remove plate
|
||||
* @param plateSlots Slots of items to randomise
|
||||
* @param armorItemAndMods Array of armor + inserts to get items from
|
||||
*/
|
||||
/// <summary>
|
||||
/// Randomise the durability values of plate items in armor <br/>
|
||||
/// Has chance to remove plate
|
||||
/// </summary>
|
||||
/// <param name="plateSlots"> Slots of items to randomise </param>
|
||||
/// <param name="armorItemAndMods"> Array of armor + inserts to get items from </param>
|
||||
protected void RandomiseArmorInsertsDurabilities(List<Slot> plateSlots, List<Item> armorItemAndMods)
|
||||
{
|
||||
foreach (var plateSlot in plateSlots)
|
||||
@@ -1334,11 +1329,11 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stack size of a singular item (no mods)
|
||||
* @param itemDbDetails item being added to fence
|
||||
* @returns Stack size
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get stack size of a singular item (no mods)
|
||||
/// </summary>
|
||||
/// <param name="itemDbDetails"> Item being added to fence </param>
|
||||
/// <returns> Stack size </returns>
|
||||
protected int GetSingleItemStackCount(TemplateItem itemDbDetails)
|
||||
{
|
||||
MinMax<int>? overrideValues;
|
||||
@@ -1374,10 +1369,10 @@ public class FenceService(
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove parts of a weapon prior to being listed on flea
|
||||
* @param itemAndMods Weapon to remove parts from
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove parts of a weapon prior to being listed on flea
|
||||
/// </summary>
|
||||
/// <param name="itemAndMods"> Weapon to remove parts from </param>
|
||||
protected void RemoveRandomModsOfItem(List<Item> itemAndMods)
|
||||
{
|
||||
// Items to be removed from inventory
|
||||
@@ -1410,12 +1405,12 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll % chance check to see if item should be removed
|
||||
* @param weaponMod Weapon mod being checked
|
||||
* @param itemsBeingDeleted Current list of items on weapon being deleted
|
||||
* @returns True if item will be removed
|
||||
*/
|
||||
/// <summary>
|
||||
/// Roll % chance check to see if item should be removed
|
||||
/// </summary>
|
||||
/// <param name="weaponMod"> Weapon mod being checked </param>
|
||||
/// <param name="itemsBeingDeleted"> Current list of items on weapon being deleted </param>
|
||||
/// <returns> True if item will be removed </returns>
|
||||
protected bool PresetModItemWillBeRemoved(Item weaponMod, HashSet<string> itemsBeingDeleted)
|
||||
{
|
||||
var slotIdsThatCanFail = traderConfig.Fence.PresetSlotsToRemoveChancePercent;
|
||||
@@ -1430,11 +1425,11 @@ public class FenceService(
|
||||
return removalChance > randomChance && !itemsBeingDeleted.Contains(weaponMod.Id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomise items' Upd properties e.g. med packs/weapons/armor
|
||||
* @param itemDetails Item being randomised
|
||||
* @param itemToAdjust Item being edited
|
||||
*/
|
||||
/// <summary>
|
||||
/// Randomise items' Upd properties e.g. med packs/weapons/armor
|
||||
/// </summary>
|
||||
/// <param name="itemDetails"> Item being randomised </param>
|
||||
/// <param name="itemToAdjust"> Item being edited </param>
|
||||
protected void RandomiseItemUpdProperties(TemplateItem itemDetails, Item itemToAdjust)
|
||||
{
|
||||
if (itemDetails.Properties == null)
|
||||
@@ -1535,12 +1530,12 @@ public class FenceService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a randomised current and max durability value for an armor item
|
||||
* @param itemDetails Item to create values for
|
||||
* @param equipmentDurabilityLimits Max durability percent min/max values
|
||||
* @returns Durability + MaxDurability values
|
||||
*/
|
||||
/// <summary>
|
||||
/// Generate a randomised current and max durability value for an armor item
|
||||
/// </summary>
|
||||
/// <param name="itemDetails"> Item to create values for </param>
|
||||
/// <param name="equipmentDurabilityLimits"> Max durability percent min/max values </param>
|
||||
/// <returns> Durability + MaxDurability values </returns>
|
||||
protected UpdRepairable GetRandomisedArmorDurabilityValues(
|
||||
TemplateItem itemDetails,
|
||||
ItemDurabilityCurrentMax equipmentDurabilityLimits
|
||||
@@ -1564,11 +1559,11 @@ public class FenceService(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct item limit record to hold max and current item count
|
||||
* @param limits limits as defined in config
|
||||
* @returns record, key: item tplId, value: current/max item count allowed
|
||||
*/
|
||||
/// <summary>
|
||||
/// Construct item limit record to hold max and current item count
|
||||
/// </summary>
|
||||
/// <param name="limits"> Limits as defined in config </param>
|
||||
/// <returns> Record, key: item tplId, value: current/max item count allowed </returns>
|
||||
protected Dictionary<string, (int current, int max)> InitItemLimitCounter(Dictionary<string, int> limits)
|
||||
{
|
||||
var itemTypeCounts = new Dictionary<string, (int current, int max)>();
|
||||
@@ -1581,10 +1576,10 @@ public class FenceService(
|
||||
return itemTypeCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next Update timestamp for fence
|
||||
* @returns future timestamp
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the next Update timestamp for fence
|
||||
/// </summary>
|
||||
/// <returns> Future timestamp </returns>
|
||||
public long GetNextFenceUpdateTimestamp()
|
||||
{
|
||||
var time = timeUtil.GetTimeStamp();
|
||||
@@ -1592,10 +1587,10 @@ public class FenceService(
|
||||
return time + updateSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fence refresh time in seconds
|
||||
* @returns Refresh time in seconds
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get fence refresh time in seconds
|
||||
/// </summary>
|
||||
/// <returns> Refresh time in seconds </returns>
|
||||
protected int GetFenceRefreshTime()
|
||||
{
|
||||
var fence = traderConfig.UpdateTime.FirstOrDefault(x => x.TraderId == Traders.FENCE).Seconds;
|
||||
@@ -1603,11 +1598,11 @@ public class FenceService(
|
||||
return randomUtil.GetInt((int) fence.Min, (int) fence.Max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fence level the passed in profile has
|
||||
* @param pmcData Player profile
|
||||
* @returns FenceLevel object
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get fence level the passed in profile has
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <returns> FenceLevel object </returns>
|
||||
public FenceLevel GetFenceInfo(PmcData pmcData)
|
||||
{
|
||||
var fenceSettings = databaseService.GetGlobals().Configuration.FenceSettings;
|
||||
@@ -1636,11 +1631,11 @@ public class FenceService(
|
||||
return fenceSettings.Levels[pmcFenceLevel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove or lower stack size of an assort from fence by id
|
||||
* @param assortId assort id to adjust
|
||||
* @param buyCount Count of items bought
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove or lower stack size of an assort from fence by id
|
||||
/// </summary>
|
||||
/// <param name="assortId"> Assort ID to adjust </param>
|
||||
/// <param name="buyCount">`Count of items bought </param>
|
||||
public void AmendOrRemoveFenceOffer(string assortId, int buyCount)
|
||||
{
|
||||
var isNormalAssort = true;
|
||||
|
||||
@@ -23,11 +23,11 @@ public class GiftService(
|
||||
{
|
||||
protected GiftsConfig _giftConfig = _configServer.GetConfig<GiftsConfig>();
|
||||
|
||||
/**
|
||||
* Does a gift with a specific ID exist in db
|
||||
* @param giftId Gift id to check for
|
||||
* @returns True if it exists in db
|
||||
*/
|
||||
/// <summary>
|
||||
/// Does a gift with a specific ID exist in db
|
||||
/// </summary>
|
||||
/// <param name="giftId"> Gift id to check for </param>
|
||||
/// <returns> True if it exists in db </returns>
|
||||
public bool GiftExists(string giftId)
|
||||
{
|
||||
return _giftConfig.Gifts.ContainsKey(giftId);
|
||||
@@ -40,30 +40,30 @@ public class GiftService(
|
||||
return gift;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dictionary of all gifts
|
||||
* @returns Dict keyed by gift id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get dictionary of all gifts
|
||||
/// </summary>
|
||||
/// <returns> Dict keyed by gift id </returns>
|
||||
public Dictionary<string, Gift> GetGifts()
|
||||
{
|
||||
return _giftConfig.Gifts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all gift ids
|
||||
* @returns string array of gift ids
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get an array of all gift ids
|
||||
/// </summary>
|
||||
/// <returns> String list of gift ids </returns>
|
||||
public List<string> GetGiftIds()
|
||||
{
|
||||
return _giftConfig.Gifts.Keys.ToList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send player a gift from a range of sources
|
||||
* @param playerId Player to send gift to / sessionId
|
||||
* @param giftId Id of gift in configs/gifts.json to send player
|
||||
* @returns outcome of sending gift to player
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send player a gift from a range of sources
|
||||
/// </summary>
|
||||
/// <param name="playerId"> Player to send gift to / sessionID </param>
|
||||
/// <param name="giftId"> ID of gift in configs/gifts.json to send player </param>
|
||||
/// <returns> Outcome of sending gift to player </returns>
|
||||
public GiftSentResult SendGiftToPlayer(string playerId, string giftId)
|
||||
{
|
||||
var giftData = GetGiftById(giftId);
|
||||
@@ -182,11 +182,11 @@ public class GiftService(
|
||||
return GiftSentResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sender id based on gifts sender type enum
|
||||
* @param giftData Gift to send player
|
||||
* @returns trader/user/system id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get sender id based on gifts sender type enum
|
||||
/// </summary>
|
||||
/// <param name="giftData"> Gift to send player </param>
|
||||
/// <returns> trader/user/system id </returns>
|
||||
private string? GetSenderId(Gift giftData)
|
||||
{
|
||||
if (giftData.Sender == GiftSenderType.Trader)
|
||||
@@ -202,11 +202,11 @@ public class GiftService(
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert GiftSenderType into a dialog MessageType
|
||||
* @param giftData Gift to send player
|
||||
* @returns MessageType enum value
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert GiftSenderType into a dialog MessageType
|
||||
/// </summary>
|
||||
/// <param name="giftData"> Gift to send player </param>
|
||||
/// <returns> MessageType enum value </returns>
|
||||
protected MessageType? GetMessageType(Gift giftData)
|
||||
{
|
||||
switch (giftData.Sender)
|
||||
@@ -223,11 +223,11 @@ public class GiftService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prapor sends gifts to player for first week after profile creation
|
||||
* @param sessionId Player id
|
||||
* @param day What day to give gift for
|
||||
*/
|
||||
/// <summary>
|
||||
/// Prapor sends gifts to player for first week after profile creation
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Player ID </param>
|
||||
/// <param name="day"> What day to give gift for </param>
|
||||
public void SendPraporStartingGift(string sessionId, int day)
|
||||
{
|
||||
var giftId = day switch
|
||||
@@ -246,12 +246,12 @@ public class GiftService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send player a gift with silent received check
|
||||
* @param giftId Id of gift to send
|
||||
* @param sessionId Session id of player to send to
|
||||
* @param giftCount OPTIONAL How many to send
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send player a gift with silent received check
|
||||
/// </summary>
|
||||
/// <param name="giftId"> ID of gift to send </param>
|
||||
/// <param name="sessionId"> Session ID of player to send to </param>
|
||||
/// <param name="giftCount"> Optional, how many to send </param>
|
||||
public void SendGiftWithSilentReceivedCheck(string giftId, string? sessionId, int giftCount)
|
||||
{
|
||||
if (!_profileHelper.PlayerHasRecievedMaxNumberOfGift(sessionId, giftId, giftCount))
|
||||
|
||||
@@ -10,17 +10,21 @@ public class InMemoryCacheService(
|
||||
{
|
||||
protected Dictionary<string, object?> _cacheData = new();
|
||||
|
||||
// Store data into an in-memory object
|
||||
// key to store data against
|
||||
// Data to store in cache
|
||||
/// <summary>
|
||||
/// Store data into an in-memory object
|
||||
/// </summary>
|
||||
/// <param name="key"> Key to store data against </param>
|
||||
/// <param name="dataToCache"> Data to store in cache </param>
|
||||
public void StoreByKey<T>(string key, T dataToCache)
|
||||
{
|
||||
_cacheData[key] = _cloner.Clone(dataToCache);
|
||||
}
|
||||
|
||||
// Retrieve data stored by a key
|
||||
// key
|
||||
// Stored data
|
||||
/// <summary>
|
||||
/// Retrieve data stored by a key
|
||||
/// </summary>
|
||||
/// <param name="key"> key</param>
|
||||
/// <returns> Stored data </returns>
|
||||
public T? GetDataByKey<T>(string key)
|
||||
{
|
||||
if (_cacheData.ContainsKey(key))
|
||||
@@ -31,22 +35,28 @@ public class InMemoryCacheService(
|
||||
return default;
|
||||
}
|
||||
|
||||
// Does data exist against the provided key
|
||||
// Key to check for data against
|
||||
// true if exists
|
||||
/// <summary>
|
||||
/// Does data exist against the provided key
|
||||
/// </summary>
|
||||
/// <param name="key"> Key to check for data against </param>
|
||||
/// <returns> True if exists </returns>
|
||||
public bool HasStoredDataByKey(string key)
|
||||
{
|
||||
return _cacheData.ContainsKey(key);
|
||||
}
|
||||
|
||||
// Remove data stored against key
|
||||
// Key to remove data against
|
||||
/// <summary>
|
||||
/// Remove data stored against key
|
||||
/// </summary>
|
||||
/// <param name="key"> Key to remove data against </param>
|
||||
public void ClearDataStoredByKey(string key)
|
||||
{
|
||||
_cacheData.Remove(key);
|
||||
}
|
||||
|
||||
// Remove all data stored
|
||||
/// <summary>
|
||||
/// Remove all data stored
|
||||
/// </summary>
|
||||
public void ClearCache()
|
||||
{
|
||||
_cacheData.Clear();
|
||||
|
||||
@@ -5,6 +5,9 @@ using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Cache the baseids for each item in the items db inside a dictionary
|
||||
/// </summary>
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class ItemBaseClassService(
|
||||
ISptLogger<ItemBaseClassService> _logger,
|
||||
@@ -15,10 +18,10 @@ public class ItemBaseClassService(
|
||||
private bool _cacheGenerated;
|
||||
private Dictionary<string, HashSet<string>> _itemBaseClassesCache;
|
||||
|
||||
/**
|
||||
* Create cache and store inside ItemBaseClassService
|
||||
* Store a dict of an items tpl to the base classes it and its parents have
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create cache and store inside ItemBaseClassService <br/>
|
||||
/// Store a dict of an items tpl to the base classes it and its parents have
|
||||
/// </summary>
|
||||
public void HydrateItemBaseClassCache()
|
||||
{
|
||||
// Clear existing cache
|
||||
@@ -40,11 +43,11 @@ public class ItemBaseClassService(
|
||||
_cacheGenerated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, recursively iterate through items parent items, finding and adding ids to dictionary
|
||||
* @param itemIdToUpdate item tpl to store base ids against in dictionary
|
||||
* @param item item being checked
|
||||
*/
|
||||
/// <summary>
|
||||
/// Helper method, recursively iterate through items parent items, finding and adding ids to dictionary
|
||||
/// </summary>
|
||||
/// <param name="itemIdToUpdate"> Item tpl to store base ids against in dictionary </param>
|
||||
/// <param name="item"> Item being checked </param>
|
||||
protected void AddBaseItems(string itemIdToUpdate, TemplateItem item)
|
||||
{
|
||||
_itemBaseClassesCache[itemIdToUpdate].Add(item.Parent);
|
||||
@@ -56,12 +59,12 @@ public class ItemBaseClassService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does item tpl inherit from the requested base class
|
||||
* @param itemTpl item to check base classes of
|
||||
* @param baseClass base class to check for
|
||||
* @returns true if item inherits from base class passed in
|
||||
*/
|
||||
/// <summary>
|
||||
/// Does item tpl inherit from the requested base class
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> ItemTpl item to check base classes of </param>
|
||||
/// <param name="baseClasses"> BaseClass base class to check for </param>
|
||||
/// <returns> true if item inherits from base class passed in </returns>
|
||||
public bool ItemHasBaseClass(string itemTpl, ICollection<string> baseClasses)
|
||||
{
|
||||
if (!_cacheGenerated)
|
||||
@@ -107,21 +110,21 @@ public class ItemBaseClassService(
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cached item template is of type Item
|
||||
* @param itemTemplateId item to check
|
||||
* @returns true if item is of type Item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if cached item template is of type Item
|
||||
/// </summary>
|
||||
/// <param name="itemTemplateId"> ItemTemplateId item to check </param>
|
||||
/// <returns> True if item is of type Item </returns>
|
||||
private bool CachedItemIsOfItemType(string itemTemplateId)
|
||||
{
|
||||
return string.Equals(_databaseService.GetItems()[itemTemplateId]?.Type,"Item", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base classes item inherits from
|
||||
* @param itemTpl item to get base classes for
|
||||
* @returns array of base classes
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get base classes item inherits from
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> ItemTpl item to get base classes for </param>
|
||||
/// <returns> array of base classes </returns>
|
||||
public List<string> GetItemBaseClasses(string itemTpl)
|
||||
{
|
||||
if (!_cacheGenerated)
|
||||
|
||||
@@ -5,7 +5,9 @@ using SPTarkov.Server.Core.Utils.Cloners;
|
||||
using SPTarkov.Common.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Centralise the handling of blacklisting items, uses blacklist found in config/item.json, stores items that should not be used by players / broken items
|
||||
/// </summary>
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class ItemFilterService(
|
||||
ISptLogger<ItemFilterService> _logger,
|
||||
@@ -18,11 +20,11 @@ public class ItemFilterService(
|
||||
|
||||
protected HashSet<string>? _lootableItemBlacklistCache = [];
|
||||
|
||||
/**
|
||||
* Check if the provided template id is blacklisted in config/item.json/blacklist
|
||||
* @param tpl template id
|
||||
* @returns true if blacklisted
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if the provided template id is blacklisted in config/item.json/blacklist
|
||||
/// </summary>
|
||||
/// <param name="tpl"> Template id</param>
|
||||
/// <returns> True if blacklisted </returns>
|
||||
public bool ItemBlacklisted(string tpl)
|
||||
{
|
||||
if (_itemBlacklistCache.Count == 0)
|
||||
@@ -33,76 +35,76 @@ public class ItemFilterService(
|
||||
return _itemBlacklistCache.Contains(tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item is blacklisted from being a reward for player
|
||||
* @param tpl item tpl to check is on blacklist
|
||||
* @returns True when blacklisted
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if item is blacklisted from being a reward for player
|
||||
/// </summary>
|
||||
/// <param name="tpl"> Item tpl to check is on blacklist </param>
|
||||
/// <returns> True when blacklisted </returns>
|
||||
public bool ItemRewardBlacklisted(string tpl)
|
||||
{
|
||||
return _itemConfig.RewardItemBlacklist.Contains(tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of items that should never be given as a reward to player
|
||||
* @returns string array of item tpls
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get an HashSet of items that should never be given as a reward to player
|
||||
/// </summary>
|
||||
/// <returns> HashSet of item tpls </returns>
|
||||
public HashSet<string> GetItemRewardBlacklist()
|
||||
{
|
||||
return _cloner.Clone(_itemConfig.RewardItemBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of item types that should never be given as a reward to player
|
||||
* @returns string array of item base ids
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get an HashSet of item types that should never be given as a reward to player
|
||||
/// </summary>
|
||||
/// <returns> HashSet of item base ids </returns>
|
||||
public HashSet<string> GetItemRewardBaseTypeBlacklist()
|
||||
{
|
||||
return _cloner.Clone(_itemConfig.RewardItemTypeBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return every template id blacklisted in config/item.json
|
||||
* @returns string array of blacklisted template ids
|
||||
*/
|
||||
/// <summary>
|
||||
/// Return every template id blacklisted in config/item.json
|
||||
/// </summary>
|
||||
/// <returns> HashSet of blacklisted template ids </returns>
|
||||
public HashSet<string> GetBlacklistedItems()
|
||||
{
|
||||
return _cloner.Clone(_itemConfig.Blacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return every template id blacklisted in config/item.json/lootableItemBlacklist
|
||||
* @returns string array of blacklisted template ids
|
||||
*/
|
||||
/// <summary>
|
||||
/// Return every template id blacklisted in config/item.json/lootableItemBlacklist
|
||||
/// </summary>
|
||||
/// <returns> HashSet of blacklisted template ids </returns>
|
||||
public HashSet<string> GetBlacklistedLootableItems()
|
||||
{
|
||||
return _cloner.Clone(_itemConfig.LootableItemBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided template id is boss item in config/item.json
|
||||
* @param tpl template id
|
||||
* @returns true if boss item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if the provided template id is boss item in config/item.json
|
||||
/// </summary>
|
||||
/// <param name="tpl"> template id </param>
|
||||
/// <returns> True if boss item </returns>
|
||||
public bool BossItem(string tpl)
|
||||
{
|
||||
return _itemConfig.BossItems.Contains(tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return boss items in config/item.json
|
||||
* @returns string array of boss item template ids
|
||||
*/
|
||||
/// <summary>
|
||||
/// Return boss items in config/item.json
|
||||
/// </summary>
|
||||
/// <returns> HashSet of boss item template ids </returns>
|
||||
public HashSet<string> GetBossItems()
|
||||
{
|
||||
return _cloner.Clone(_itemConfig.BossItems).ToHashSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided template id is blacklisted in config/item.json/lootableItemBlacklist
|
||||
* @param tpl template id
|
||||
* @returns true if blacklisted
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if the provided template id is blacklisted in config/item.json/lootableItemBlacklist
|
||||
/// </summary>
|
||||
/// <param name="itemKey"> Template id</param>
|
||||
/// <returns> True if blacklisted </returns>
|
||||
public bool IsLootableItemBlacklisted(string itemKey)
|
||||
{
|
||||
if (!_lootableItemBlacklistCache.Any())
|
||||
@@ -139,21 +141,21 @@ public class ItemFilterService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided template id is boss item in config/item.json
|
||||
* @param tpl template id
|
||||
* @returns true if boss item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if the provided template id is boss item in config/item.json
|
||||
/// </summary>
|
||||
/// <param name="tpl"> Template id</param>
|
||||
/// <returns> True if boss item </returns>
|
||||
public bool IsBossItem(string tpl)
|
||||
{
|
||||
return _itemConfig.BossItems.Contains(tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item is blacklisted from being a reward for player
|
||||
* @param tpl item tpl to check is on blacklist
|
||||
* @returns True when blacklisted
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if item is blacklisted from being a reward for player
|
||||
/// </summary>
|
||||
/// <param name="tpl"> Item tpl to check is on blacklist </param>
|
||||
/// <returns> true when blacklisted </returns>
|
||||
public bool IsItemRewardBlacklisted(string tpl)
|
||||
{
|
||||
return _itemConfig.RewardItemBlacklist.Contains(tpl);
|
||||
|
||||
@@ -15,10 +15,10 @@ public class LocaleService(
|
||||
{
|
||||
protected LocaleConfig _localeConfig = _configServer.GetConfig<LocaleConfig>();
|
||||
|
||||
/**
|
||||
* Get the eft globals db file based on the configured locale in config/locale.json, if not found, fall back to 'en'
|
||||
* @returns dictionary
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the eft globals db file based on the configured locale in config/locale.json, if not found, fall back to 'en'
|
||||
/// </summary>
|
||||
/// <returns> Dictionary </returns>
|
||||
public Dictionary<string, string> GetLocaleDb()
|
||||
{
|
||||
if (_databaseServer.GetTables().Locales.Global.TryGetValue(GetDesiredGameLocale(), out var desiredLocale))
|
||||
@@ -33,11 +33,11 @@ public class LocaleService(
|
||||
return _databaseServer.GetTables().Locales.Global["en"].Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the game locale key from the locale.json file,
|
||||
* if value is 'system' get system locale
|
||||
* @returns locale e.g en/ge/cz/cn
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the game locale key from the locale.json file,
|
||||
/// if value is 'system' get system locale
|
||||
/// </summary>
|
||||
/// <returns> Locale e.g en/ge/cz/cn </returns>
|
||||
public string GetDesiredGameLocale()
|
||||
{
|
||||
if (_localeConfig.GameLocale.ToLower() == "system")
|
||||
@@ -48,11 +48,11 @@ public class LocaleService(
|
||||
return _localeConfig.GameLocale.ToLower();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the game locale key from the locale.json file,
|
||||
* if value is 'system' get system locale
|
||||
* @returns locale e.g en/ge/cz/cn
|
||||
*/
|
||||
/// <summary>
|
||||
/// Gets the game locale key from the locale.json file,
|
||||
/// if value is 'system' get system locale
|
||||
/// </summary>
|
||||
/// <returns> Locale e.g en/ge/cz/cn </returns>
|
||||
public string GetDesiredServerLocale()
|
||||
{
|
||||
if (_localeConfig.ServerLocale.ToLower() == "system")
|
||||
@@ -63,28 +63,28 @@ public class LocaleService(
|
||||
return _localeConfig.ServerLocale.ToLower();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of languages supported for localisation
|
||||
* @returns array of locales e.g. en/fr/cn
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get array of languages supported for localisation
|
||||
/// </summary>
|
||||
/// <returns> List of locales e.g. en/fr/cn </returns>
|
||||
public List<string> GetServerSupportedLocales()
|
||||
{
|
||||
return _localeConfig.ServerSupportedLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of languages supported for localisation
|
||||
* @returns array of locales e.g. en/fr/cn
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get array of languages supported for localisation
|
||||
/// </summary>
|
||||
/// <returns> Dictionary of locales e.g. en/fr/cn </returns>
|
||||
public Dictionary<string, string> GetLocaleFallbacks()
|
||||
{
|
||||
return _localeConfig.Fallbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full locale of the computer running the server lowercased e.g. en-gb / pt-pt
|
||||
* @returns string
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the full locale of the computer running the server lowercased e.g. en-gb / pt-pt
|
||||
/// </summary>
|
||||
/// <returns> System locale as String </returns>
|
||||
public string GetPlatformForServerLocale()
|
||||
{
|
||||
var platformLocale = GetPlatformLocale();
|
||||
@@ -124,10 +124,10 @@ public class LocaleService(
|
||||
return baseNameCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale of the computer running the server
|
||||
* @returns langage part of locale e.g. 'en' part of 'en-US'
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the locale of the computer running the server
|
||||
/// </summary>
|
||||
/// <returns> Language part of locale e.g. 'en' part of 'en-US' </returns>
|
||||
protected string GetPlatformForClientLocale()
|
||||
{
|
||||
var platformLocale = GetPlatformLocale();
|
||||
@@ -150,12 +150,11 @@ public class LocaleService(
|
||||
return languageCode;
|
||||
}
|
||||
|
||||
/*
|
||||
const regionCode = platformLocale.region?.toLocaleLowerCase();
|
||||
if (regionCode && locales.global[regionCode]) {
|
||||
return regionCode;
|
||||
}
|
||||
*/
|
||||
//
|
||||
// const regionCode = platformLocale.region?.toLocaleLowerCase();
|
||||
// if (regionCode && locales.global[regionCode]) {
|
||||
// return regionCode;
|
||||
// }
|
||||
|
||||
// BSG map DE to GE some reason
|
||||
if (baseNameCode == "de")
|
||||
@@ -167,10 +166,10 @@ public class LocaleService(
|
||||
return "en";
|
||||
}
|
||||
|
||||
/**
|
||||
* This is in a function so we can overwrite it during testing
|
||||
* @returns The current platform locale
|
||||
*/
|
||||
/// <summary>
|
||||
/// This is in a function so we can overwrite it during testing
|
||||
/// </summary>
|
||||
/// <returns> The current platform locale </returns>
|
||||
protected CultureInfo GetPlatformLocale()
|
||||
{
|
||||
return CultureInfo.InstalledUICulture;
|
||||
|
||||
@@ -5,6 +5,9 @@ using SPTarkov.Common.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Handles translating server text into different langauges
|
||||
/// </summary>
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class LocalisationService
|
||||
{
|
||||
@@ -41,7 +44,12 @@ public class LocalisationService
|
||||
);
|
||||
_i18nService.SetLocaleByKey(localeService.GetDesiredServerLocale());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a localised value using the passed in key
|
||||
/// </summary>
|
||||
/// <param name="key"> Key to look up locale for </param>
|
||||
/// <param name="args"> optional arguments </param>
|
||||
/// <returns> Localised string </returns>
|
||||
public string GetText(string key, object? args = null)
|
||||
{
|
||||
return args is null
|
||||
@@ -49,16 +57,31 @@ public class LocalisationService
|
||||
: _i18nService.GetLocalised(key, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a localised value using the passed in key
|
||||
/// </summary>
|
||||
/// <param name="key"> Key to look up locale for </param>
|
||||
/// <param name="value"> Value to localize </param>
|
||||
/// <returns> Localised string </returns>
|
||||
public string GetText<T>(string key, T value) where T : IConvertible?
|
||||
{
|
||||
return _i18nService.GetLocalised(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all locale keys
|
||||
/// </summary>
|
||||
/// <returns> Generic collection of keys </returns>
|
||||
public ICollection<string> GetKeys()
|
||||
{
|
||||
return _i18nService.GetLocalisedKeys();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// From the provided partial key, find all keys that start with text and choose a random match
|
||||
/// </summary>
|
||||
/// <param name="partialKey"> Key to match locale keys on </param>
|
||||
/// <returns> Locale text </returns>
|
||||
public string GetRandomTextThatMatchesPartialKey(string partialKey)
|
||||
{
|
||||
var values = _localeService.GetLocaleKeysThatStartsWithValue(partialKey);
|
||||
|
||||
@@ -124,9 +124,9 @@ public class LocationLifecycleService
|
||||
_pmcConfig = _configServer.GetConfig<PmcConfig>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle client/match/local/start
|
||||
*/
|
||||
/// <summary>
|
||||
/// Handle client/match/local/start
|
||||
/// </summary>
|
||||
public virtual StartLocalRaidResponseData StartLocalRaid(string sessionId, StartLocalRaidRequestData request)
|
||||
{
|
||||
_logger.Debug($"Starting: {request.Location}");
|
||||
@@ -196,12 +196,12 @@ public class LocationLifecycleService
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace map exits with scav exits when player is scavving
|
||||
* @param playerSide Players side (savage/usec/bear)
|
||||
* @param location id of map being loaded
|
||||
* @param locationData Maps location base data
|
||||
*/
|
||||
/// <summary>
|
||||
/// Replace map exits with scav exits when player is scavving
|
||||
/// </summary>
|
||||
/// <param name="playerSide"> Players side (savage/usec/bear) </param>
|
||||
/// <param name="location"> ID of map being loaded </param>
|
||||
/// <param name="locationData"> Maps location base data </param>
|
||||
protected void AdjustExtracts(string playerSide, string location, LocationBase locationData)
|
||||
{
|
||||
var playerIsScav = playerSide.ToLower() == "savage";
|
||||
@@ -228,10 +228,10 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the bot hostility values prior to entering a raid
|
||||
* @param location map to adjust values of
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adjust the bot hostility values prior to entering a raid
|
||||
/// </summary>
|
||||
/// <param name="location"> Map to adjust values of </param>
|
||||
protected void AdjustBotHostilitySettings(LocationBase location)
|
||||
{
|
||||
foreach (var botId in _pmcConfig.HostilitySettings)
|
||||
@@ -322,12 +322,18 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a maps base location (cloned) and loot
|
||||
* @param name Map name
|
||||
* @param generateLoot OPTIONAL - Should loot be generated for the map before being returned
|
||||
* @returns LocationBase
|
||||
*/
|
||||
/// <summary>
|
||||
/// Generate a maps base location (cloned) and loot
|
||||
/// </summary>
|
||||
/// <param name="name"> Map name </param>
|
||||
/// <param name="generateLoot"> OPTIONAL - Should loot be generated for the map before being returned </param>
|
||||
/// <returns> LocationBase </returns>
|
||||
/// <returns> LocationBase </returns>
|
||||
/// <param name="generateLoot"> OPTIONAL - Should loot be generated for the map before being returned </param>
|
||||
/// <param name="name"> Map name </param>
|
||||
/// </summary>
|
||||
/// Generate a maps base location (cloned) and loot
|
||||
/// <summary>
|
||||
public virtual LocationBase GenerateLocationAndLoot(string name, bool generateLoot = true)
|
||||
{
|
||||
var location = _databaseService.GetLocation(name);
|
||||
@@ -401,9 +407,9 @@ public class LocationLifecycleService
|
||||
return locationBaseClone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle client/match/local/end
|
||||
*/
|
||||
/// <summary>
|
||||
/// Handle client/match/local/end
|
||||
/// </summary>
|
||||
public virtual void EndLocalRaid(string sessionId, EndLocalRaidRequestData request)
|
||||
{
|
||||
// Clear bot loot cache
|
||||
@@ -510,11 +516,11 @@ public class LocationLifecycleService
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Was extract by car
|
||||
* @param extractName name of extract
|
||||
* @returns True if extract was by car
|
||||
*/
|
||||
/// <summary>
|
||||
/// Was extract by car
|
||||
/// </summary>
|
||||
/// <param name="extractName"> Name of extract </param>
|
||||
/// <returns> True if extract was by car </returns>
|
||||
protected bool ExtractWasViaCar(string extractName)
|
||||
{
|
||||
// exit name is undefined on death
|
||||
@@ -531,12 +537,12 @@ public class LocationLifecycleService
|
||||
return _inRaidConfig.CarExtracts.Contains(extractName.Trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle when a player extracts using a car - Add rep to fence
|
||||
* @param extractName name of the extract used
|
||||
* @param pmcData Player profile
|
||||
* @param sessionId Session id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Handle when a player extracts using a car - Add rep to fence
|
||||
/// </summary>
|
||||
/// <param name="extractName"> Name of the extract used </param>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
protected void HandleCarExtract(string extractName, PmcData pmcData, string sessionId)
|
||||
{
|
||||
pmcData.CarExtractCounts?.TryAdd(extractName, 0);
|
||||
@@ -565,12 +571,12 @@ public class LocationLifecycleService
|
||||
scavData.TradersInfo[fenceId].LoyaltyLevel = pmcData.TradersInfo[fenceId].LoyaltyLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle when a player extracts using a coop extract - add rep to fence
|
||||
* @param sessionId Session/player id
|
||||
* @param pmcData Profile
|
||||
* @param extractName Name of extract taken
|
||||
*/
|
||||
/// <summary>
|
||||
/// Handle when a player extracts using a coop extract - add rep to fence
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session/player id </param>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <param name="extractName"> Name of extract taken </param>
|
||||
protected void HandleCoopExtract(string sessionId, PmcData pmcData, string extractName)
|
||||
{
|
||||
pmcData.CoopExtractCounts?.TryAdd(extractName, 0);
|
||||
@@ -598,13 +604,13 @@ public class LocationLifecycleService
|
||||
scavData.TradersInfo[fenceId].LoyaltyLevel = pmcData.TradersInfo[fenceId].LoyaltyLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fence rep gain from using a car or coop extract
|
||||
* @param pmcData Profile
|
||||
* @param baseGain amount gained for the first extract
|
||||
* @param extractCount Number of times extract was taken
|
||||
* @returns Fence standing after taking extract
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the fence rep gain from using a car or coop extract
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Profile </param>
|
||||
/// <param name="baseGain"> Amount gained for the first extract </param>
|
||||
/// <param name="extractCount"> Number of times extract was taken </param>
|
||||
/// <returns> Fence standing after taking extract </returns>
|
||||
protected double GetFenceStandingAfterExtract(PmcData pmcData, double baseGain, double extractCount)
|
||||
{
|
||||
const string fenceId = Traders.FENCE;
|
||||
@@ -620,11 +626,11 @@ public class LocationLifecycleService
|
||||
return Math.Round(newFenceStanding, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Did player take a COOP extract
|
||||
* @param extractName Name of extract player took
|
||||
* @returns True if coop extract
|
||||
*/
|
||||
/// <summary>
|
||||
/// Did player take a COOP extract
|
||||
/// </summary>
|
||||
/// <param name="extractName"> Name of extract player took </param>
|
||||
/// <returns> True if coop extract </returns>
|
||||
protected bool ExtractTakenWasCoop(string extractName)
|
||||
{
|
||||
// No extract name, not a coop extract
|
||||
@@ -709,11 +715,11 @@ public class LocationLifecycleService
|
||||
_saveServer.SaveProfile(sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scav quest progress isnt transferred automatically from scav to pmc, we do this manually
|
||||
* @param scavProfile Scav profile with quest progress post-raid
|
||||
* @param pmcProfile Server pmc profile to copy scav quest progress into
|
||||
*/
|
||||
/// <summary>
|
||||
/// Scav quest progress isn't transferred automatically from scav to pmc, we do this manually
|
||||
/// </summary>
|
||||
/// <param name="scavProfile"> Scav profile with quest progress post-raid </param>
|
||||
/// <param name="pmcProfile"> Server pmc profile to copy scav quest progress into </param>
|
||||
private void MigrateScavQuestProgressToPmcProfile(PmcData scavProfile, PmcData pmcProfile)
|
||||
{
|
||||
foreach (var scavQuest in scavProfile.Quests)
|
||||
@@ -753,11 +759,11 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does provided profile contain any condition counters
|
||||
* @param profile Profile to check for condition counters
|
||||
* @returns Profile has condition counters
|
||||
*/
|
||||
/// <summary>
|
||||
/// Does the provided profile contain any condition counters
|
||||
/// </summary>
|
||||
/// <param name="profile"> Profile to check for condition counters </param>
|
||||
/// <returns> Profile has condition counters </returns>
|
||||
protected bool ProfileHasConditionCounters(PmcData profile)
|
||||
{
|
||||
if (profile.TaskConditionCounters is null)
|
||||
@@ -768,15 +774,17 @@ public class LocationLifecycleService
|
||||
return profile.TaskConditionCounters.Count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sessionId Player id
|
||||
* @param pmcProfile Pmc profile
|
||||
* @param scavProfile Scav profile
|
||||
* @param isDead Player died/got left behind in raid
|
||||
* @param isSurvived Not same as opposite of `isDead`, specific status
|
||||
* @param request
|
||||
* @param locationName
|
||||
*/
|
||||
/// <summary>
|
||||
/// Handles PMC Profile after the raid
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Player id </param>
|
||||
/// <param name="fullProfile"> Pmc profile </param>
|
||||
/// <param name="scavProfile"> Scav profile </param>
|
||||
/// <param name="isDead"> Player died/got left behind in raid </param>
|
||||
/// <param name="isSurvived"> Not same as opposite of `isDead`, specific status </param>
|
||||
/// <param name="isTransfer"> Player transferred to another map </param>
|
||||
/// <param name="request"> Client request data </param>
|
||||
/// <param name="locationName"> Current finished Raid location </param>
|
||||
protected void HandlePostRaidPmc(
|
||||
string sessionId,
|
||||
SptProfile fullProfile,
|
||||
@@ -884,6 +892,13 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On death Quest items are lost, the client does not clean up completed conditions for picking up those quest items,
|
||||
/// If the completed conditions remain in the profile the player is unable to pick the item up again
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="lostQuestItems"> Quest items lost on player death </param>
|
||||
/// <param name="profileQuests"> Quest status data from player profile </param>
|
||||
protected void CheckForAndFixPickupQuestsAfterDeath(
|
||||
string sessionId,
|
||||
List<Item> lostQuestItems,
|
||||
@@ -953,11 +968,16 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In 0.15 Lightkeeper quests do not give rewards in PvE, this issue also occurs in spt
|
||||
* We check for newly completed Lk quests and run them through the servers `CompleteQuest` process
|
||||
* This rewards players with items + craft unlocks + new trader assorts
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// In 0.15 Lightkeeper quests do not give rewards in PvE, this issue also occurs in spt.
|
||||
/// We check for newly completed Lk quests and run them through the servers `CompleteQuest` process.
|
||||
/// This rewards players with items + craft unlocks + new trader assorts.
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="postRaidQuests"> Quest statuses post-raid </param>
|
||||
/// <param name="preRaidQuests"> Quest statuses pre-raid </param>
|
||||
/// <param name="pmcProfile"> Players profile </param>
|
||||
protected void LightkeeperQuestWorkaround(
|
||||
string sessionId,
|
||||
List<QuestStatus> postRaidQuests,
|
||||
@@ -997,10 +1017,12 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert post-raid quests into correct format
|
||||
* Quest status comes back as a string version of the enum `Success`, not the expected value of 1
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert post-raid quests into correct format.
|
||||
/// Quest status comes back as a string version of the enum `Success`, not the expected value of 1.
|
||||
/// </summary>
|
||||
/// <param name="questsToProcess"> Quests data from client </param>
|
||||
/// <returns> List of adjusted QuestStatus post-raid </returns>
|
||||
protected List<QuestStatus> ProcessPostRaidQuests(List<QuestStatus> questsToProcess)
|
||||
{
|
||||
var failedQuests = questsToProcess.Where(quest => quest.Status == QuestStatusEnum.MarkedAsFailed);
|
||||
@@ -1021,9 +1043,11 @@ public class LocationLifecycleService
|
||||
return questsToProcess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust server trader settings if they differ from data sent by client
|
||||
*/
|
||||
/// <summary>
|
||||
/// Adjust server trader settings if they differ from data sent by client
|
||||
/// </summary>
|
||||
/// <param name="tradersServerProfile"> Server </param>
|
||||
/// <param name="tradersClientProfile"> Client </param>
|
||||
protected void ApplyTraderStandingAdjustments(
|
||||
Dictionary<string, TraderInfo>? tradersServerProfile,
|
||||
Dictionary<string, TraderInfo>? tradersClientProfile
|
||||
@@ -1046,9 +1070,11 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if player used BTR or transit item sending service and send items to player via mail if found
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check if player used BTR or transit item sending service and send items to player via mail if found
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="request"> End raid request from client </param>
|
||||
protected void HandleItemTransferEvent(string sessionId, EndLocalRaidRequestData request)
|
||||
{
|
||||
var transferTypes = new List<string>
|
||||
@@ -1147,17 +1173,21 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if player survives. run through will return false
|
||||
*/
|
||||
/// <summary>
|
||||
/// Checks to see if player survives. run through will return false
|
||||
/// </summary>
|
||||
/// <param name="results"> Post raid request </param>
|
||||
/// <returns> True if survived </returns>
|
||||
protected bool IsPlayerSurvived(EndRaidResult results)
|
||||
{
|
||||
return results.Result == ExitStatus.SURVIVED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the player dead after a raid - dead = anything other than "survived" / "runner"
|
||||
*/
|
||||
/// <summary>
|
||||
/// Is the player dead after a raid - dead = anything other than "survived" / "runner"
|
||||
/// </summary>
|
||||
/// <param name="results"> Post raid request </param>
|
||||
/// <returns> True if dead </returns>
|
||||
protected bool IsPlayerDead(EndRaidResult results)
|
||||
{
|
||||
var deathEnums = new List<ExitStatus>
|
||||
@@ -1169,17 +1199,20 @@ public class LocationLifecycleService
|
||||
return deathEnums.Contains(results.Result.Value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Has the player moved from one map to another
|
||||
*/
|
||||
/// <summary>
|
||||
/// Has the player moved from one map to another
|
||||
/// </summary>
|
||||
/// <param name="results"> Post raid request </param>
|
||||
/// <returns> True if players transferred </returns>
|
||||
protected bool IsMapToMapTransfer(EndRaidResult results)
|
||||
{
|
||||
return results.Result == ExitStatus.TRANSIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the skill points earned in a raid to 0, ready for next raid
|
||||
*/
|
||||
/// <summary>
|
||||
/// Reset the skill points earned in a raid to 0, ready for next raid
|
||||
/// </summary>
|
||||
/// <param name="commonSkills"> Profile common skills to update </param>
|
||||
protected void ResetSkillPointsEarnedDuringRaid(List<BaseSkill> commonSkills)
|
||||
{
|
||||
foreach (var skill in commonSkills)
|
||||
@@ -1188,10 +1221,12 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* merge two dictionaries together
|
||||
* Prioritise pair that has true as a value
|
||||
*/
|
||||
/// <summary>
|
||||
/// Merge two dictionaries together.
|
||||
/// Prioritise pair that has true as a value
|
||||
/// </summary>
|
||||
/// <param name="primary"> Main dictionary </param>
|
||||
/// <param name="secondary"> Secondary dictionary </param>
|
||||
protected void MergePmcAndScavEncyclopedias(PmcData primary, PmcData secondary)
|
||||
{
|
||||
var mergedDicts = primary.Encyclopedia?.Union(secondary.Encyclopedia)
|
||||
@@ -1205,6 +1240,11 @@ public class LocationLifecycleService
|
||||
secondary.Encyclopedia = mergedDicts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for and add any rewards found via the gained achievements this raid
|
||||
/// </summary>
|
||||
/// <param name="fullProfile"> Profile to add customisations to </param>
|
||||
/// <param name="postRaidAchievements"> All profile achievements at the end of a raid </param>
|
||||
protected void ProcessAchievementRewards(SptProfile fullProfile, Dictionary<string, long>? postRaidAchievements)
|
||||
{
|
||||
var sessionId = fullProfile.ProfileInfo.ProfileId;
|
||||
|
||||
@@ -31,15 +31,17 @@ public class MailSendService(
|
||||
protected HashSet<MessageType> _messageTypes = [MessageType.NPC_TRADER, MessageType.FLEAMARKET_MESSAGE];
|
||||
protected HashSet<string> _slotNames = ["hideout", "main"];
|
||||
|
||||
/**
|
||||
* Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale
|
||||
* @param sessionId The session ID to send the message to
|
||||
* @param trader The trader sending the message
|
||||
* @param messageType What type the message will assume (e.g. QUEST_SUCCESS)
|
||||
* @param message Text to send to the player
|
||||
* @param items Optional items to send to player
|
||||
* @param maxStorageTimeSeconds Optional time to collect items before they expire
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> The session ID to send the message to </param>
|
||||
/// <param name="trader"> The trader sending the message </param>
|
||||
/// <param name="messageType"> What type the message will assume (e.g. QUEST_SUCCESS) </param>
|
||||
/// <param name="message"> Text to send to the player </param>
|
||||
/// <param name="items"> Optional items to send to player </param>
|
||||
/// <param name="maxStorageTimeSeconds"> Optional time to collect items before they expire </param>
|
||||
/// <param name="systemData"> </param>
|
||||
/// <param name="ragfair"> </param>
|
||||
public void SendDirectNpcMessageToPlayer(
|
||||
string sessionId,
|
||||
string? trader,
|
||||
@@ -97,15 +99,17 @@ public class MailSendService(
|
||||
SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message from an NPC (e.g. prapor) to the player with or without items
|
||||
* @param sessionId The session ID to send the message to
|
||||
* @param trader The trader sending the message
|
||||
* @param messageType What type the message will assume (e.g. QUEST_SUCCESS)
|
||||
* @param messageLocaleId The localised text to send to player
|
||||
* @param items Optional items to send to player
|
||||
* @param maxStorageTimeSeconds Optional time to collect items before they expire
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send a message from an NPC (e.g. prapor) to the player with or without items
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> The session ID to send the message to </param>
|
||||
/// <param name="trader"> The trader sending the message </param>
|
||||
/// <param name="messageType"> What type the message will assume (e.g. QUEST_SUCCESS) </param>
|
||||
/// <param name="messageLocaleId"> The localised text to send to player </param>
|
||||
/// <param name="items"> Optional items to send to player </param>
|
||||
/// <param name="maxStorageTimeSeconds"> Optional time to collect items before they expire </param>
|
||||
/// <param name="systemData"></param>
|
||||
/// <param name="ragfair"></param>
|
||||
public void SendLocalisedNpcMessageToPlayer(
|
||||
string sessionId,
|
||||
string? trader,
|
||||
@@ -171,13 +175,14 @@ public class MailSendService(
|
||||
SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message from SYSTEM to the player with or without items
|
||||
* @param sessionId The session ID to send the message to
|
||||
* @param message The text to send to player
|
||||
* @param items Optional items to send to player
|
||||
* @param maxStorageTimeSeconds Optional time to collect items before they expire
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send a message from SYSTEM to the player with or without items
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> The session ID to send the message to </param>
|
||||
/// <param name="message"> The text to send to player </param>
|
||||
/// <param name="items"> Optional items to send to player </param>
|
||||
/// <param name="maxStorageTimeSeconds"> Optional time to collect items before they expire </param>
|
||||
/// <param name="profileChangeEvents"></param>
|
||||
public void SendSystemMessageToPlayer(
|
||||
string sessionId,
|
||||
string message,
|
||||
@@ -209,7 +214,14 @@ public class MailSendService(
|
||||
|
||||
SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a message from SYSTEM to the player with or without items with localised text
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> The session ID to send the message to </param>
|
||||
/// <param name="messageLocaleId"> Id of key from locale file to send to player </param>
|
||||
/// <param name="items"> Optional items to send to player </param>
|
||||
/// <param name="profileChangeEvents"></param>
|
||||
/// <param name="maxStorageTimeSeconds"> Optional time to collect items before they expire </param>
|
||||
public void SendLocalisedSystemMessageToPlayer(
|
||||
string sessionId,
|
||||
string messageLocaleId,
|
||||
@@ -241,14 +253,14 @@ public class MailSendService(
|
||||
SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a USER message to a player with or without items
|
||||
* @param sessionId The session ID to send the message to
|
||||
* @param senderId Who is sending the message
|
||||
* @param message The text to send to player
|
||||
* @param items Optional items to send to player
|
||||
* @param maxStorageTimeSeconds Optional time to collect items before they expire
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send a USER message to a player with or without items
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> The session ID to send the message to </param>
|
||||
/// <param name="senderDetails"> Who is sending the message </param>
|
||||
/// <param name="message"> The text to send to player </param>
|
||||
/// <param name="items"> Optional items to send to player </param>
|
||||
/// <param name="maxStorageTimeSeconds"> Optional time to collect items before they expire </param>
|
||||
public void SendUserMessageToPlayer(
|
||||
string sessionId,
|
||||
UserDialogInfo senderDetails,
|
||||
@@ -276,11 +288,11 @@ public class MailSendService(
|
||||
SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER)
|
||||
* Helper functions in this class are available to simplify common actions
|
||||
* @param messageDetails Details needed to send a message to the player
|
||||
*/
|
||||
/// <summary>
|
||||
/// Large function to send messages to players from a variety of sources (SYSTEM/NPC/USER).
|
||||
/// Helper functions in this class are available to simplify common actions
|
||||
/// </summary>
|
||||
/// <param name="messageDetails"> Details needed to send a message to the player </param>
|
||||
public void SendMessageToPlayer(SendMessageDetails messageDetails)
|
||||
{
|
||||
// Get dialog, create if doesn't exist
|
||||
@@ -332,6 +344,12 @@ public class MailSendService(
|
||||
_notificationSendHelper.SendMessage(messageDetails.RecipientId, notificationMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a message from the player to an NPC
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="targetNpcId"> NPC message is sent to </param>
|
||||
/// <param name="message"> Text to send to NPC </param>
|
||||
public void SendPlayerMessageToNpc(string sessionId, string targetNpcId, string message)
|
||||
{
|
||||
var playerProfile = _saveServer.GetProfile(sessionId);
|
||||
@@ -356,6 +374,12 @@ public class MailSendService(
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a message for storage inside a dialog in the player profile
|
||||
/// </summary>
|
||||
/// <param name="dialogId"> ID of dialog that will hold the message </param>
|
||||
/// <param name="messageDetails"> Various details on what the message must contain/do </param>
|
||||
/// <returns> Message </returns>
|
||||
private Message CreateDialogMessage(string dialogId, SendMessageDetails messageDetails)
|
||||
{
|
||||
Message message = new()
|
||||
@@ -385,12 +409,13 @@ public class MailSendService(
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param recipientId The id of the recipient
|
||||
* @param replyToId The id of the message to reply to
|
||||
* @param dialogueId The id of the dialogue (traderId or profileId)
|
||||
* @returns A new instance with data from the found message, otherwise undefined
|
||||
*/
|
||||
/// <summary>
|
||||
/// Finds the Message to reply to using the ID of the recipient, message and the dialogue.
|
||||
/// </summary>
|
||||
/// <param name="recipientId"> The ID of the recipient </param>
|
||||
/// <param name="replyToId"> The ID of the message to reply to </param>
|
||||
/// <param name="dialogueId"> The ID of the dialogue (traderId or profileId) </param>
|
||||
/// <returns> A new instance with data from the found message, otherwise undefined </returns>
|
||||
protected ReplyTo? GetMessageToReplyTo(string recipientId, string replyToId, string dialogueId)
|
||||
{
|
||||
var currentDialogue = _dialogueHelper.GetDialogueFromProfile(recipientId, dialogueId);
|
||||
@@ -417,12 +442,12 @@ public class MailSendService(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add items to message and adjust various properties to reflect the items being added
|
||||
* @param message Message to add items to
|
||||
* @param itemsToSendToPlayer Items to add to message
|
||||
* @param maxStorageTimeSeconds total time items are stored in mail before being deleted
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add items to message and adjust various properties to reflect the items being added
|
||||
/// </summary>
|
||||
/// <param name="message"> Message to add items to </param>
|
||||
/// <param name="itemsToSendToPlayer"> Items to add to message </param>
|
||||
/// <param name="maxStorageTimeSeconds"> Total time the items are stored in mail before being deleted </param>
|
||||
private void AddRewardItemsToMessage(Message message, MessageItems? itemsToSendToPlayer, long? maxStorageTimeSeconds)
|
||||
{
|
||||
if ((itemsToSendToPlayer?.Data?.Count ?? 0) > 0)
|
||||
@@ -434,6 +459,12 @@ public class MailSendService(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform various sanitising actions on the items before they're considered ready for insertion into message
|
||||
/// </summary>
|
||||
/// <param name="dialogType"> The type of the dialog that will hold the reward items being processed </param>
|
||||
/// <param name="messageDetails"> Details fo the message e.g. Text, items it has etc. </param>
|
||||
/// <returns> Sanitised items </returns>
|
||||
private MessageItems ProcessItemsBeforeAddingToMail(MessageType? dialogType, SendMessageDetails messageDetails)
|
||||
{
|
||||
var items = _databaseService.GetItems();
|
||||
@@ -544,11 +575,11 @@ public class MailSendService(
|
||||
return itemsToSendToPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find the most correct item to be the 'primary' item in a reward mail
|
||||
* @param items Possible items to choose from
|
||||
* @returns Chosen 'primary' item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Try to find the most correct item to be the 'primary' item in a reward mail
|
||||
/// </summary>
|
||||
/// <param name="items"> Possible items to choose from </param>
|
||||
/// <returns> Chosen 'primary' item </returns>
|
||||
private Item GetBaseItemFromRewards(List<Item>? items)
|
||||
{
|
||||
// Only one item in reward, return it
|
||||
@@ -576,12 +607,13 @@ public class MailSendService(
|
||||
return items[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a dialog with a specified entity (user/trader)
|
||||
* Create and store empty dialog if none exists in profile
|
||||
* @param messageDetails Data on what message should do
|
||||
* @returns Relevant Dialogue
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get a dialog with a specified entity (user/trader).
|
||||
/// Create and store empty dialog if none exists in profile.
|
||||
/// </summary>
|
||||
/// <param name="messageDetails"> Data on what message should do </param>
|
||||
/// <returns> Relevant Dialogue object </returns>
|
||||
/// <exception cref="Exception"> Thrown when message not found </exception>
|
||||
private Dialogue GetDialog(SendMessageDetails messageDetails)
|
||||
{
|
||||
var senderId = GetMessageSenderIdByType(messageDetails);
|
||||
@@ -610,11 +642,11 @@ public class MailSendService(
|
||||
return dialogsInProfile[senderId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate sender id by the sender enum type
|
||||
* @param messageDetails
|
||||
* @returns gets an id of the individual sending it
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the appropriate sender id by the sender enum type
|
||||
/// </summary>
|
||||
/// <param name="messageDetails"> Data of the message </param>
|
||||
/// <returns> Gets an id of the individual sending it </returns>
|
||||
private string? GetMessageSenderIdByType(SendMessageDetails messageDetails)
|
||||
{
|
||||
if (messageDetails.Sender == MessageType.SYSTEM_MESSAGE)
|
||||
|
||||
@@ -5,6 +5,9 @@ using SPTarkov.Common.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Cache bots in a dictionary, keyed by the bots name, keying by name isnt ideal as its not unique but this is used by the post-raid system which doesnt have any bot ids, only name
|
||||
/// </summary>
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class MatchBotDetailsCacheService(
|
||||
ISptLogger<MatchBotDetailsCacheService> _logger,
|
||||
@@ -13,6 +16,10 @@ public class MatchBotDetailsCacheService(
|
||||
{
|
||||
protected ConcurrentDictionary<string, BotBase> _botDetailsCache = new();
|
||||
|
||||
/// <summary>
|
||||
/// Store a bot in the cache, keyed by its name.
|
||||
/// </summary>
|
||||
/// <param name="botToCache"> Bot details to cache </param>
|
||||
public void CacheBot(BotBase botToCache)
|
||||
{
|
||||
if (botToCache.Info.Nickname is null)
|
||||
@@ -29,11 +36,20 @@ public class MatchBotDetailsCacheService(
|
||||
_botDetailsCache.TryAdd(key, botToCache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean the cache of all bot details.
|
||||
/// </summary>
|
||||
public void ClearCache()
|
||||
{
|
||||
_botDetailsCache.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a bot in the cache by its name and side.
|
||||
/// </summary>
|
||||
/// <param name="botName"> Name of bot to find </param>
|
||||
/// <param name="botSide"> Side of the bot </param>
|
||||
/// <returns></returns>
|
||||
public BotBase? GetBotByNameAndSide(string botName, string botSide)
|
||||
{
|
||||
var botInCache = _botDetailsCache.GetValueOrDefault($"{botName}{botSide}`", null);
|
||||
|
||||
@@ -20,16 +20,16 @@ public class CustomItemService(
|
||||
ICloner cloner
|
||||
)
|
||||
{
|
||||
/**
|
||||
* Create a new item from a cloned item base
|
||||
* WARNING - If no item id is supplied, an id will be generated, this id will be random every time you add an item and will not be the same on each subsequent server start
|
||||
* Add to the items db
|
||||
* Add to the flea market
|
||||
* Add to the handbook
|
||||
* Add to the locales
|
||||
* @param newItemDetails Item details for the new item to be created
|
||||
* @returns tplId of the new item created
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new item from a cloned item base <br/>
|
||||
/// WARNING - If no item id is supplied, an id will be generated, this id will be random every time you add an item and will not be the same on each subsequent server start <br/>
|
||||
/// Add to the items db <br/>
|
||||
/// Add to the flea market <br/>
|
||||
/// Add to the handbook <br/>
|
||||
/// Add to the locales
|
||||
/// </summary>
|
||||
/// <param name="newItemDetails"> Item details for the new item to be created </param>
|
||||
/// <returns> tplId of the new item created </returns>
|
||||
public CreateItemResult CreateItemFromClone(NewItemFromCloneDetails newItemDetails)
|
||||
{
|
||||
var result = new CreateItemResult();
|
||||
@@ -78,15 +78,15 @@ public class CustomItemService(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new item without using an existing item as a template
|
||||
* Add to the items db
|
||||
* Add to the flea market
|
||||
* Add to the handbook
|
||||
* Add to the locales
|
||||
* @param newItemDetails Details on what the item to be created
|
||||
* @returns CreateItemResult containing the completed items Id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create a new item without using an existing item as a template <br/>
|
||||
/// Add to the items db <br/>
|
||||
/// Add to the flea market <br/>
|
||||
/// Add to the handbook <br/>
|
||||
/// Add to the locales <br/>
|
||||
/// </summary>
|
||||
/// <param name="newItemDetails"> Details on what the item to be created </param>
|
||||
/// <returns> CreateItemResult containing the completed items ID </returns>
|
||||
public CreateItemResult CreateItem(NewItemDetails newItemDetails)
|
||||
{
|
||||
var result = new CreateItemResult();
|
||||
@@ -122,22 +122,22 @@ public class CustomItemService(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the id provided is an empty string, return a randomly generated guid, otherwise return the newId parameter
|
||||
* @param newId id supplied to code
|
||||
* @returns item id
|
||||
*/
|
||||
/// <summary>
|
||||
/// If the ID provided is an empty string, return a randomly generated guid, otherwise return the newId parameter
|
||||
/// </summary>
|
||||
/// <param name="newId"> ID supplied to code </param>
|
||||
/// <returns> ItemID </returns>
|
||||
protected string GetOrGenerateIdForItem(string newId)
|
||||
{
|
||||
return newId == "" ? hashUtil.Generate() : newId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through supplied properties and updates the cloned items properties with them
|
||||
* Complex objects cannot have overrides, they must be fully hydrated with values if they are to be used
|
||||
* @param overrideProperties new properties to apply
|
||||
* @param itemClone item to update
|
||||
*/
|
||||
/// <summary>
|
||||
/// Iterates through supplied properties and updates the cloned items properties with them
|
||||
/// Complex objects cannot have overrides, they must be fully hydrated with values if they are to be used
|
||||
/// </summary>
|
||||
/// <param name="overrideProperties"> New properties to apply </param>
|
||||
/// <param name="itemClone"> Item to update </param>
|
||||
protected void UpdateBaseItemPropertiesWithOverrides(Props? overrideProperties, TemplateItem itemClone)
|
||||
{
|
||||
if (overrideProperties is null)
|
||||
@@ -151,11 +151,11 @@ public class CustomItemService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new item object to the in-memory representation of items.json
|
||||
* @param newItemId id of the item to add to items.json
|
||||
* @param itemToAdd Item to add against the new id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add a new item object to the in-memory representation of items.json
|
||||
/// </summary>
|
||||
/// <param name="newItemId"> ID of the item to add to items.json </param>
|
||||
/// <param name="itemToAdd"> Item to add against the new id </param>
|
||||
protected void AddToItemsDb(string newItemId, TemplateItem itemToAdd)
|
||||
{
|
||||
if (!databaseService.GetItems().TryAdd(newItemId, itemToAdd))
|
||||
@@ -164,12 +164,12 @@ public class CustomItemService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a handbook price for an item
|
||||
* @param newItemId id of the item being added
|
||||
* @param parentId parent id of the item being added
|
||||
* @param priceRoubles price of the item being added
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add a handbook price for an item
|
||||
/// </summary>
|
||||
/// <param name="newItemId"> ID of the item being added </param>
|
||||
/// <param name="parentId"> Parent ID of the item being added </param>
|
||||
/// <param name="priceRoubles"> Price of the item being added </param>
|
||||
protected void AddToHandbookDb(string newItemId, string parentId, double? priceRoubles)
|
||||
{
|
||||
databaseService
|
||||
@@ -185,17 +185,17 @@ public class CustomItemService(
|
||||
// TODO: would we want to keep this the same or get them to send a HandbookItem
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through the passed in locale data and add to each locale in turn
|
||||
* If data is not provided for each language EFT uses, the first object will be used in its place
|
||||
* e.g.
|
||||
* en[0]
|
||||
* fr[1]
|
||||
*
|
||||
* No jp provided, so english will be used as a substitute
|
||||
* @param localeDetails key is language, value are the new locale details
|
||||
* @param newItemId id of the item being created
|
||||
*/
|
||||
/// <summary>
|
||||
/// Iterate through the passed in locale data and add to each locale in turn <br/>
|
||||
/// If data is not provided for each language EFT uses, the first object will be used in its place <br/>
|
||||
/// e.g. <br/>
|
||||
/// en[0] <br/>
|
||||
/// fr[1] <br/>
|
||||
/// <br/>
|
||||
/// No jp provided, so english will be used as a substitute
|
||||
/// </summary>
|
||||
/// <param name="localeDetails"> key is language, value are the new locale details </param>
|
||||
/// <param name="newItemId"> ID of the item being created </param>
|
||||
protected void AddToLocaleDbs(Dictionary<string, LocaleDetails> localeDetails, string newItemId)
|
||||
{
|
||||
var languages = databaseService.GetLocales().Languages;
|
||||
@@ -220,20 +220,20 @@ public class CustomItemService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a price to the in-memory representation of prices.json, used to inform the flea of an items price on the market
|
||||
* @param newItemId id of the new item
|
||||
* @param fleaPriceRoubles Price of the new item
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add a price to the in-memory representation of prices.json, used to inform the flea of an items price on the market
|
||||
/// </summary>
|
||||
/// <param name="newItemId"> ID of the new item </param>
|
||||
/// <param name="fleaPriceRoubles"> Price of the new item </param>
|
||||
protected void AddToFleaPriceDb(string newItemId, double? fleaPriceRoubles)
|
||||
{
|
||||
databaseService.GetTemplates().Prices[newItemId] = fleaPriceRoubles ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a weapon to the hideout weapon shelf whitelist
|
||||
* @param newItemId Weapon id to add
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add a weapon to the hideout weapon shelf whitelist
|
||||
/// </summary>
|
||||
/// <param name="newItemId"> Weapon ID to add </param>
|
||||
protected void AddToWeaponShelf(string newItemId)
|
||||
{
|
||||
// Ids for wall stashes in db
|
||||
@@ -253,12 +253,12 @@ public class CustomItemService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom weapon to PMCs loadout
|
||||
* @param weaponTpl Custom weapon tpl to add to PMCs
|
||||
* @param weaponWeight The weighting for the weapon to be picked vs other weapons
|
||||
* @param weaponSlot The slot the weapon should be added to (e.g. FirstPrimaryWeapon/SecondPrimaryWeapon/Holster)
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add a custom weapon to PMCs loadout
|
||||
/// </summary>
|
||||
/// <param name="weaponTpl"> Custom weapon tpl to add to PMCs </param>
|
||||
/// <param name="weaponWeight"> The weighting for the weapon to be picked vs other weapons </param>
|
||||
/// <param name="weaponSlot"> The slot the weapon should be added to (e.g. FirstPrimaryWeapon/SecondPrimaryWeapon/Holster) </param>
|
||||
public void AddCustomWeaponToPMCs(string weaponTpl, double weaponWeight, string weaponSlot)
|
||||
{
|
||||
var weapon = itemHelper.GetItem(weaponTpl);
|
||||
|
||||
@@ -5,6 +5,9 @@ using SPTarkov.Common.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Service for adding new zones to a maps OpenZones property.
|
||||
/// </summary>
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class OpenZoneService(
|
||||
ISptLogger<OpenZoneService> _logger,
|
||||
|
||||
@@ -31,13 +31,13 @@ public class PaymentService(
|
||||
{
|
||||
protected InventoryConfig _inventoryConfig = _configServer.GetConfig<InventoryConfig>();
|
||||
|
||||
/**
|
||||
* Take money and insert items into return to server request
|
||||
* @param pmcData Pmc profile
|
||||
* @param request Buy item request
|
||||
* @param sessionID Session id
|
||||
* @param output Client response
|
||||
*/
|
||||
/// <summary>
|
||||
/// Take money and insert items into return to server request
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> PMC Profile </param>
|
||||
/// <param name="request"> Buy item request </param>
|
||||
/// <param name="sessionID"> Session ID </param>
|
||||
/// <param name="output"> Client response </param>
|
||||
public void PayMoney(PmcData pmcData, ProcessBuyTradeRequestData request, string sessionID, ItemEventRouterResponse output)
|
||||
{
|
||||
// May need to convert to trader currency
|
||||
@@ -142,6 +142,12 @@ public class PaymentService(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the item price of a specific traders assort
|
||||
/// </summary>
|
||||
/// <param name="traderAssortId"> ID of the assort to look up</param>
|
||||
/// <param name="traderId"> ID of trader with assort </param>
|
||||
/// <returns> Handbook rouble price of the item </returns>
|
||||
private double? GetTraderItemHandbookPriceRouble(string? traderAssortId, string traderId)
|
||||
{
|
||||
var purchasedAssortItem = _traderHelper.GetTraderAssortItemByAssortId(traderId, traderAssortId);
|
||||
@@ -161,6 +167,14 @@ public class PaymentService(
|
||||
return assortItemPriceRouble;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receive money back after selling
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> PMC Profile</param>
|
||||
/// <param name="amountToSend"> Money to send back </param>
|
||||
/// <param name="request"> Sell Trade request data </param>
|
||||
/// <param name="output"> Client response </param>
|
||||
/// <param name="sessionID"> Session ID </param>
|
||||
public void GiveProfileMoney(PmcData pmcData, double? amountToSend, ProcessSellTradeRequestData request,
|
||||
ItemEventRouterResponse output, string sessionID)
|
||||
{
|
||||
@@ -256,14 +270,14 @@ public class PaymentService(
|
||||
_traderHelper.LevelUp(request.TransactionId, pmcData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove currency from player stash/inventory and update client object with changes
|
||||
* @param pmcData Player profile to find and remove currency from
|
||||
* @param currencyTpl Type of currency to pay
|
||||
* @param amountToPay money value to pay
|
||||
* @param sessionID Session id
|
||||
* @param output output object to send to client
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove currency from player stash/inventory and update client object with changes
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Player profile to find and remove currency from</param>
|
||||
/// <param name="currencyTpl"> Type of currency to pay </param>
|
||||
/// <param name="amountToPay"> Money value to pay </param>
|
||||
/// <param name="sessionID"> Session ID </param>
|
||||
/// <param name="output"> Client response </param>
|
||||
public void AddPaymentToOutput(
|
||||
PmcData pmcData,
|
||||
string currencyTpl,
|
||||
@@ -337,14 +351,14 @@ public class PaymentService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - ensure money in containers inside secure container are LAST
|
||||
* Get all money stacks in inventory and prioritise items in stash
|
||||
* @param pmcData Player profile
|
||||
* @param currencyTpl
|
||||
* @param playerStashId Players stash id
|
||||
* @returns Sorting money items
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get all money stacks in inventory and prioritise items in stash
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <param name="currencyTpl"> Currency to find </param>
|
||||
/// <param name="playerStashId"> Players stash ID </param>
|
||||
/// <returns> List of sorted money items </returns>
|
||||
// TODO - ensure money in containers inside secure container are LAST
|
||||
protected List<Item> GetSortedMoneyItemsInInventory(PmcData pmcData, string currencyTpl, string playerStashId)
|
||||
{
|
||||
var moneyItemsInInventory = _itemHelper.FindBarterItems("tpl", pmcData.Inventory.Items, currencyTpl);
|
||||
@@ -359,15 +373,15 @@ public class PaymentService(
|
||||
return moneyItemsInInventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prioritise player stash first over player inventory
|
||||
* Post-raid healing would often take money out of the players pockets/secure container
|
||||
* @param a First money stack item
|
||||
* @param b Second money stack item
|
||||
* @param inventoryItems players inventory items
|
||||
* @param playerStashId Players stash id
|
||||
* @returns sort order
|
||||
*/
|
||||
/// <summary>
|
||||
/// Prioritise player stash first over player inventory.
|
||||
/// Post-raid healing would often take money out of the players pockets/secure container.
|
||||
/// </summary>
|
||||
/// <param name="a"> First money stack item </param>
|
||||
/// <param name="b"> Second money stack item </param>
|
||||
/// <param name="inventoryItems"> Players inventory items </param>
|
||||
/// <param name="playerStashId"> Players stash ID </param>
|
||||
/// <returns> Sort order, -1 if in a, 1 if in b, 0 if they match </returns>
|
||||
protected int PrioritiseStashSort(Item a, Item b, List<Item> inventoryItems, string playerStashId)
|
||||
{
|
||||
// a in root of stash, prioritise
|
||||
@@ -433,13 +447,13 @@ public class PaymentService(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively check items parents to see if it is inside the players inventory, not stash
|
||||
* @param itemId item id to check
|
||||
* @param inventoryItems player inventory
|
||||
* @param playerStashId Players stash id
|
||||
* @returns true if its in inventory
|
||||
*/
|
||||
/// <summary>
|
||||
/// Recursively check items parents to see if it is inside the players inventory, not stash
|
||||
/// </summary>
|
||||
/// <param name="itemId"> Item ID to check </param>
|
||||
/// <param name="inventoryItems"> Player inventory </param>
|
||||
/// <param name="playerStashId"> Players stash ID </param>
|
||||
/// <returns> True if it's in inventory </returns>
|
||||
protected bool IsInStash(string itemId, List<Item> inventoryItems, string playerStashId)
|
||||
{
|
||||
var itemParent = inventoryItems.FirstOrDefault(item => item.Id == itemId);
|
||||
|
||||
@@ -8,11 +8,11 @@ public class PlayerService(
|
||||
DatabaseService _databaseService
|
||||
)
|
||||
{
|
||||
/**
|
||||
* Get level of player
|
||||
* @param pmcData Player profile
|
||||
* @returns Level of player
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get level of player
|
||||
/// </summary>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <returns> Level of the player </returns>
|
||||
public int? CalculateLevel(PmcData pmcData)
|
||||
{
|
||||
var accExp = 0;
|
||||
|
||||
@@ -29,12 +29,12 @@ public class PmcChatResponseService(
|
||||
protected GiftsConfig _giftConfig = _configServer.GetConfig<GiftsConfig>();
|
||||
protected PmcChatResponse _pmcResponsesConfig = _configServer.GetConfig<PmcChatResponse>();
|
||||
|
||||
/**
|
||||
* For each PMC victim of the player, have a chance to send a message to the player, can be positive or negative
|
||||
* @param sessionId Session id
|
||||
* @param pmcVictims List of bots killed by player
|
||||
* @param pmcData Player profile
|
||||
*/
|
||||
/// <summary>
|
||||
/// For each PMC victim of the player, have a chance to send a message to the player, can be positive or negative
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="pmcVictims"> List of bots killed by player </param>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
public void SendVictimResponse(string sessionId, List<Victim> pmcVictims, PmcData pmcData)
|
||||
{
|
||||
foreach (var victim in pmcVictims)
|
||||
@@ -65,12 +65,12 @@ public class PmcChatResponseService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not fully implemented yet, needs method of acquiring killers details after raid
|
||||
* @param sessionId Session id
|
||||
* @param pmcData Players profile
|
||||
* @param killer The bot who killed the player
|
||||
*/
|
||||
/// <summary>
|
||||
/// Not fully implemented yet, needs method of acquiring killers details after raid
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session id </param>
|
||||
/// <param name="pmcData"> Players profile </param>
|
||||
/// <param name="killer"> The bot who killed the player </param>
|
||||
public void SendKillerResponse(string sessionId, PmcData pmcData, Aggressor killer)
|
||||
{
|
||||
if (killer is null)
|
||||
@@ -128,13 +128,13 @@ public class PmcChatResponseService(
|
||||
_notificationSendHelper.SendMessageToPlayer(sessionId, killerDetails, message, MessageType.USER_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a localised message to send the player (different if sender was killed or killed player)
|
||||
* @param isVictim Is the message coming from a bot killed by the player
|
||||
* @param pmcData Player profile
|
||||
* @param victimData OPTIMAL - details of the pmc killed
|
||||
* @returns Message from PMC to player
|
||||
*/
|
||||
/// <summary>
|
||||
/// Choose a localised message to send the player (different if sender was killed or killed player)
|
||||
/// </summary>
|
||||
/// <param name="isVictim"> Is the message coming from a bot killed by the player </param>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <param name="victimData"> OPTIONAL - details of the pmc killed </param>
|
||||
/// <returns> Message from PMC to player </returns>
|
||||
protected string? ChooseMessage(bool isVictim, PmcData pmcData, Victim? victimData = null)
|
||||
{
|
||||
// Positive/negative etc
|
||||
@@ -189,22 +189,22 @@ public class PmcChatResponseService(
|
||||
return responseText;
|
||||
}
|
||||
|
||||
/**
|
||||
* use map key to get a localised location name
|
||||
* e.g. factory4_day becomes "Factory"
|
||||
* @param locationKey location key to localise
|
||||
* @returns Localised location name
|
||||
*/
|
||||
/// <summary>
|
||||
/// use map key to get a localised location name
|
||||
/// e.g. factory4_day becomes "Factory"
|
||||
/// </summary>
|
||||
/// <param name="locationKey"> Location key to localise </param>
|
||||
/// <returns> Localised location name </returns>
|
||||
protected string GetLocationName(string locationKey)
|
||||
{
|
||||
return _localeService.GetLocaleDb()[locationKey] ?? locationKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should capitalisation be stripped from the message response before sending
|
||||
* @param isVictim Was responder a victim of player
|
||||
* @returns true = should be stripped
|
||||
*/
|
||||
/// <summary>
|
||||
/// Should capitalisation be stripped from the message response before sending
|
||||
/// </summary>
|
||||
/// <param name="isVictim"> Was responder a victim of player </param>
|
||||
/// <returns> True = should be stripped </returns>
|
||||
protected bool StripCapitalisation(bool isVictim)
|
||||
{
|
||||
var chance = isVictim
|
||||
@@ -214,11 +214,11 @@ public class PmcChatResponseService(
|
||||
return _randomUtil.GetChance100(chance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should capitalisation be stripped from the message response before sending
|
||||
* @param isVictim Was responder a victim of player
|
||||
* @returns true = should be stripped
|
||||
*/
|
||||
/// <summary>
|
||||
/// Should capitalisation be stripped from the message response before sending
|
||||
/// </summary>
|
||||
/// <param name="isVictim"> Was responder a victim of player </param>
|
||||
/// <returns> True = should be stripped </returns>
|
||||
protected bool AllCaps(bool isVictim)
|
||||
{
|
||||
var chance = isVictim
|
||||
@@ -228,11 +228,11 @@ public class PmcChatResponseService(
|
||||
return _randomUtil.GetChance100(chance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should a suffix be appended to the end of the message being sent to player
|
||||
* @param isVictim Was responder a victim of player
|
||||
* @returns true = should be stripped
|
||||
*/
|
||||
/// <summary>
|
||||
/// Should a suffix be appended to the end of the message being sent to player
|
||||
/// </summary>
|
||||
/// <param name="isVictim"> Was responder a victim of player </param>
|
||||
/// <returns> True = should be appended </returns>
|
||||
protected bool AppendSuffixToMessageEnd(bool isVictim)
|
||||
{
|
||||
var chance = isVictim
|
||||
@@ -242,11 +242,11 @@ public class PmcChatResponseService(
|
||||
return _randomUtil.GetChance100(chance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a type of response based on the weightings in pmc response config
|
||||
* @param isVictim Was responder killed by player
|
||||
* @returns Response type (positive/negative)
|
||||
*/
|
||||
/// <summary>
|
||||
/// Choose a type of response based on the weightings in pmc response config
|
||||
/// </summary>
|
||||
/// <param name="isVictim"> Was responder killed by player </param>
|
||||
/// <returns> Response type (positive/negative) </returns>
|
||||
protected string ChooseResponseType(bool isVictim = true)
|
||||
{
|
||||
var responseWeights = isVictim
|
||||
@@ -256,12 +256,12 @@ public class PmcChatResponseService(
|
||||
return _weightedRandomHelper.GetWeightedValue<string>(responseWeights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get locale keys related to the type of response to send (victim/killer)
|
||||
* @param keyType Positive/negative
|
||||
* @param isVictim Was responder killed by player
|
||||
* @returns
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get locale keys related to the type of response to send (victim/killer)
|
||||
/// </summary>
|
||||
/// <param name="keyType"> Positive/negative </param>
|
||||
/// <param name="isVictim"> Was responder killed by player </param>
|
||||
/// <returns>List of response locale keys </returns>
|
||||
protected List<string> GetResponseLocaleKeys(string keyType, bool isVictim = true)
|
||||
{
|
||||
var keyBase = isVictim ? "pmcresponse-victim_" : "pmcresponse-killer_";
|
||||
@@ -270,10 +270,10 @@ public class PmcChatResponseService(
|
||||
return keys.Where(x => x.StartsWith($"{keyBase}{keyType}")).ToList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all locale keys that start with `pmcresponse-suffix`
|
||||
* @returns list of keys
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get all locale keys that start with `pmcresponse-suffix`
|
||||
/// </summary>
|
||||
/// <returns> List of keys </returns>
|
||||
protected List<string> GetResponseSuffixLocaleKeys()
|
||||
{
|
||||
var keys = _localisationService.GetKeys();
|
||||
@@ -281,12 +281,12 @@ public class PmcChatResponseService(
|
||||
return keys.Where(x => x.StartsWith("pmcresponse-suffix")).ToList();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: is this used?
|
||||
* Randomly draw a victim of the list and return their details
|
||||
* @param pmcVictims Possible victims to choose from
|
||||
* @returns IUserDialogInfo
|
||||
*/
|
||||
/// <summary>
|
||||
/// Randomly draw a victim of the list and return their details
|
||||
/// </summary>
|
||||
/// <param name="pmcVictims"> Possible victims to choose from </param>
|
||||
/// <returns> UserDialogInfo object </returns>
|
||||
// TODO: is this used?
|
||||
protected UserDialogInfo ChooseRandomVictim(List<Victim> pmcVictims)
|
||||
{
|
||||
var randomVictim = _randomUtil.GetArrayValue(pmcVictims);
|
||||
@@ -294,11 +294,11 @@ public class PmcChatResponseService(
|
||||
return GetVictimDetails(randomVictim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a victim object into a IUserDialogInfo object
|
||||
* @param pmcVictim victim to convert
|
||||
* @returns IUserDialogInfo
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert a victim object into a IUserDialogInfo object
|
||||
/// </summary>
|
||||
/// <param name="pmcVictim"> Victim to convert </param>
|
||||
/// <returns> UserDialogInfo object </returns>
|
||||
protected UserDialogInfo GetVictimDetails(Victim pmcVictim)
|
||||
{
|
||||
var categories = new List<MemberCategory>
|
||||
|
||||
@@ -275,7 +275,9 @@ public class PostDbLoadService(
|
||||
}
|
||||
}
|
||||
|
||||
// Apply custom limits on bot types as defined in configs/location.json/botTypeLimits
|
||||
/// <summary>
|
||||
/// Apply custom limits on bot types as defined in configs/location.json/botTypeLimits
|
||||
/// </summary>
|
||||
protected void AdjustMapBotLimits()
|
||||
{
|
||||
var mapsDb = _databaseService.GetLocations().GetDictionary();
|
||||
@@ -386,7 +388,9 @@ public class PostDbLoadService(
|
||||
}
|
||||
}
|
||||
|
||||
// Make Rogues spawn later to allow for scavs to spawn first instead of rogues filling up all spawn positions
|
||||
/// <summary>
|
||||
/// Make Rogues spawn later to allow for scavs to spawn first instead of rogues filling up all spawn positions
|
||||
/// </summary>
|
||||
protected void FixRoguesSpawningInstantlyOnLighthouse()
|
||||
{
|
||||
var rogueSpawnDelaySeconds = _locationConfig.RogueLighthouseSpawnTimeSettings.WaitTimeSeconds;
|
||||
@@ -406,7 +410,9 @@ public class PostDbLoadService(
|
||||
}
|
||||
}
|
||||
|
||||
// Make non-trigger-spawned raiders spawn earlier + always
|
||||
/// <summary>
|
||||
/// Make non-trigger-spawned raiders spawn earlier + always
|
||||
/// </summary>
|
||||
protected void AdjustLabsRaiderSpawnRate()
|
||||
{
|
||||
var labsBase = _databaseService.GetLocations().Laboratory.Base;
|
||||
@@ -437,7 +443,10 @@ public class PostDbLoadService(
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust all hideout craft times to be no higher than the override
|
||||
/// <summary>
|
||||
/// Adjust all hideout craft times to be no higher than the override
|
||||
/// </summary>
|
||||
/// <param name="overrideSeconds"> Time in seconds </param>
|
||||
protected void AdjustHideoutBuildTimes(int overrideSeconds)
|
||||
{
|
||||
if (overrideSeconds == -1)
|
||||
@@ -472,7 +481,9 @@ public class PostDbLoadService(
|
||||
}
|
||||
}
|
||||
|
||||
// Blank out the "test" mail message from prapor
|
||||
/// <summary>
|
||||
/// Blank out the "test" mail message from prapor
|
||||
/// </summary>
|
||||
protected void RemovePraporTestMessage()
|
||||
{
|
||||
// Iterate over all languages (e.g. "en", "fr")
|
||||
@@ -483,7 +494,9 @@ public class PostDbLoadService(
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any missing assorts inside each traders assort.json data, checking against traders questassort.json
|
||||
/// <summary>
|
||||
/// Check for any missing assorts inside each traders assort.json data, checking against traders questassort.json
|
||||
/// </summary>
|
||||
protected void ValidateQuestAssortUnlocksExist()
|
||||
{
|
||||
var db = _databaseService.GetTables();
|
||||
|
||||
@@ -10,12 +10,12 @@ public class ProfileActivityService(
|
||||
{
|
||||
private readonly Dictionary<string, long> profileActivityTimestamps = new();
|
||||
|
||||
/**
|
||||
* Was the requested profile active in the last requested minutes
|
||||
* @param sessionId Profile to check
|
||||
* @param minutes Minutes to check for activity in
|
||||
* @returns True when profile was active within past x minutes
|
||||
*/
|
||||
/// <summary>
|
||||
/// Was the requested profile active in the last requested minutes
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Profile to check </param>
|
||||
/// <param name="minutes"> Minutes to check for activity in </param>
|
||||
/// <returns> True when profile was active within past x minutes </returns>
|
||||
public bool ActiveWithinLastMinutes(string sessionId, int minutes)
|
||||
{
|
||||
var currentTimestamp = _timeUtil.GetTimeStamp();
|
||||
@@ -27,11 +27,11 @@ public class ProfileActivityService(
|
||||
return currentTimestamp - storedActivityTimestamp < minutes * 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of profile ids that were active in the last x minutes
|
||||
* @param minutes How many minutes from now to search for profiles
|
||||
* @returns List of profile ids
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get a list of profile ids that were active in the last x minutes
|
||||
/// </summary>
|
||||
/// <param name="minutes"> How many minutes from now to search for profiles </param>
|
||||
/// <returns> List of profile ids </returns>
|
||||
public List<string> GetActiveProfileIdsWithinMinutes(int minutes)
|
||||
{
|
||||
var currentTimestamp = _timeUtil.GetTimeStamp();
|
||||
@@ -55,10 +55,10 @@ public class ProfileActivityService(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the timestamp a profile was last observed active
|
||||
* @param sessionId Profile to update
|
||||
*/
|
||||
/// <summary>
|
||||
/// Update the timestamp a profile was last observed active
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Profile to update </param>
|
||||
public void SetActivityTimestamp(string sessionId)
|
||||
{
|
||||
profileActivityTimestamps[sessionId] = _timeUtil.GetTimeStamp();
|
||||
|
||||
@@ -401,11 +401,11 @@ public class ProfileFixerService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any entries from `pmcProfile.InsuredItems` that do not have a corresponding
|
||||
* `pmcProfile.Inventory.items` entry
|
||||
* @param pmcProfile
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove any entries from `pmcProfile.InsuredItems` that do not have a corresponding
|
||||
/// `pmcProfile.Inventory.items` entry
|
||||
/// </summary>
|
||||
/// <param name="pmcProfile"> PMC Profile to fix </param>
|
||||
protected void FixOrphanedInsurance(PmcData pmcProfile) {
|
||||
|
||||
// Check if the player inventory contains this item
|
||||
@@ -526,10 +526,10 @@ public class ProfileFixerService(
|
||||
return slots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for and cap profile skills at 5100.
|
||||
* @param pmcProfile profile to check and fix
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check for and cap profile skills at 5100.
|
||||
/// </summary>
|
||||
/// <param name="pmcProfile"> Profile to check and fix </param>
|
||||
protected void CheckForSkillsOverMaxLevel(PmcData pmcProfile)
|
||||
{
|
||||
var skills = pmcProfile.Skills.Common;
|
||||
@@ -540,11 +540,11 @@ public class ProfileFixerService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks profile inventory for items that do not exist inside the items db
|
||||
* @param sessionId Session id
|
||||
* @param pmcProfile Profile to check inventory of
|
||||
*/
|
||||
/// <summary>
|
||||
/// Checks profile inventory for items that do not exist inside the items DB
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="fullProfile"> Profile to check inventory of </param>
|
||||
public void CheckForOrphanedModdedItems(string sessionId, SptProfile fullProfile)
|
||||
{
|
||||
var itemsDb = _databaseService.GetItems();
|
||||
@@ -720,12 +720,13 @@ public class ProfileFixerService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buildType The type of build, used for logging only
|
||||
* @param build The build to check for invalid items
|
||||
* @param itemsDb The items database to use for item lookup
|
||||
* @returns True if the build should be removed from the build list, false otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Check whether a weapon build should be removed from the equipment list.
|
||||
/// </summary>
|
||||
/// <param name="buildType"> The type of build, used for logging only </param>
|
||||
/// <param name="build"> The build to check for invalid items </param>
|
||||
/// <param name="itemsDb"> The items database to use for item lookup </param>
|
||||
/// <returns> True if the build should be removed from the build list, false otherwise </returns>
|
||||
protected bool ShouldRemoveWeaponEquipmentBuild(
|
||||
string buildType,
|
||||
UserBuild build,
|
||||
@@ -773,11 +774,12 @@ public class ProfileFixerService(
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param magazineBuild The magazine build to check for validity
|
||||
* @param itemsDb The items database to use for item lookup
|
||||
* @returns True if the build should be removed from the build list, false otherwise
|
||||
*/
|
||||
/// <summary>
|
||||
/// Checks whether magazine build shou8ld be removed form the build list.
|
||||
/// </summary>
|
||||
/// <param name="magazineBuild"> The magazine build to check for validity </param>
|
||||
/// <param name="itemsDb"> The items database to use for item lookup </param>
|
||||
/// <returns> True if the build should be removed from the build list, false otherwise </returns>
|
||||
protected bool ShouldRemoveMagazineBuild(
|
||||
MagazineBuild magazineBuild,
|
||||
Dictionary<string, TemplateItem> itemsDb)
|
||||
@@ -809,11 +811,11 @@ public class ProfileFixerService(
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* REQUIRED for dev profiles
|
||||
* Iterate over players hideout areas and find what's built, look for missing bonuses those areas give and add them if missing
|
||||
* @param pmcProfile Profile to update
|
||||
*/
|
||||
/// <summary>
|
||||
/// REQUIRED for dev profiles <br/>
|
||||
/// Iterate over players hideout areas and find what's built, look for missing bonuses those areas give and add them if missing
|
||||
/// </summary>
|
||||
/// <param name="pmcProfile"> Profile to update </param>
|
||||
public void AddMissingHideoutBonusesToProfile(PmcData pmcProfile)
|
||||
{
|
||||
var dbHideoutAreas = _databaseService.GetHideout().Areas;
|
||||
@@ -869,11 +871,12 @@ public class ProfileFixerService(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param profileBonuses bonuses from profile
|
||||
* @param bonus bonus to find
|
||||
* @returns matching bonus
|
||||
*/
|
||||
/// <summary>
|
||||
/// Finds a bonus in a profile
|
||||
/// </summary>
|
||||
/// <param name="profileBonuses"> Bonuses from profile </param>
|
||||
/// <param name="bonus"> Bonus to find </param>
|
||||
/// <returns> Matching bonus </returns>
|
||||
protected Bonus? GetBonusFromProfile(List<Bonus>? profileBonuses, Bonus bonus)
|
||||
{
|
||||
// match by id first, used by "TextBonus" bonuses
|
||||
|
||||
@@ -27,11 +27,11 @@ public class RagfairLinkedItemService(
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use ragfair linked item service to get an array of items that can fit on or in designated itemtpl
|
||||
* @param itemTpl Item to get sub-items for
|
||||
* @returns ITemplateItem array
|
||||
*/
|
||||
/// <summary>
|
||||
/// Use ragfair linked item service to get an list of items that can fit on or in designated itemtpl
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> Item to get sub-items for </param>
|
||||
/// <returns> TemplateItem list </returns>
|
||||
public List<TemplateItem> GetLinkedDbItems(string itemTpl)
|
||||
{
|
||||
var linkedItemsToWeaponTpls = GetLinkedItems(itemTpl);
|
||||
@@ -54,9 +54,9 @@ public class RagfairLinkedItemService(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Dictionary of every item and the items associated with it
|
||||
*/
|
||||
/// <summary>
|
||||
/// Create Dictionary of every item and the items associated with it
|
||||
/// </summary>
|
||||
protected void BuildLinkedItemTable()
|
||||
{
|
||||
var linkedItems = new Dictionary<string, HashSet<string>>();
|
||||
@@ -92,11 +92,11 @@ public class RagfairLinkedItemService(
|
||||
return linkedItems[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add ammo to revolvers linked item dictionary
|
||||
* @param cylinder Revolvers cylinder
|
||||
* @param applyLinkedItems
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add ammo to revolvers linked item dictionary
|
||||
/// </summary>
|
||||
/// <param name="cylinder"> Revolvers cylinder </param>
|
||||
/// <param name="itemLinkedSet"> Set to add to </param>
|
||||
protected void AddRevolverCylinderAmmoToLinkedItems(TemplateItem cylinder, HashSet<string> itemLinkedSet)
|
||||
{
|
||||
var cylinderMod = cylinder.Properties.Slots?.FirstOrDefault(x => x.Name == "mod_magazine");
|
||||
|
||||
@@ -30,10 +30,10 @@ public class RagfairOfferService(
|
||||
protected bool _playerOffersLoaded;
|
||||
protected RagfairConfig _ragfairConfig = configServer.GetConfig<RagfairConfig>();
|
||||
|
||||
/**
|
||||
* Get all offers
|
||||
* @returns RagfairOffer array
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get all offers
|
||||
/// </summary>
|
||||
/// <returns> List of RagfairOffers </returns>
|
||||
public List<RagfairOffer> GetOffers()
|
||||
{
|
||||
return ragfairOfferHolder.GetOffers();
|
||||
@@ -54,30 +54,30 @@ public class RagfairOfferService(
|
||||
ragfairOfferHolder.AddOffer(offer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the offer exist on the ragfair
|
||||
* @param offerId offer id to check for
|
||||
* @returns offer exists - true
|
||||
*/
|
||||
/// <summary>
|
||||
/// Does the offer exist on the ragfair
|
||||
/// </summary>
|
||||
/// <param name="offerId"> Offer id to check for </param>
|
||||
/// <returns> True when offer exists </returns>
|
||||
public bool DoesOfferExist(string offerId)
|
||||
{
|
||||
return ragfairOfferHolder.GetOfferById(offerId) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an offer from ragfair by offer id
|
||||
* @param offerId Offer id to remove
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove an offer from ragfair by offer id
|
||||
/// </summary>
|
||||
/// <param name="offerId"> Offer id to remove </param>
|
||||
public void RemoveOfferById(string offerId)
|
||||
{
|
||||
ragfairOfferHolder.RemoveOffer(offerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce size of an offer stack by specified amount
|
||||
* @param offerId Offer to adjust stack size of
|
||||
* @param amount How much to deduct from offers stack size
|
||||
*/
|
||||
/// <summary>
|
||||
/// Reduce size of an offer stack by specified amount
|
||||
/// </summary>
|
||||
/// <param name="offerId"> Offer to adjust stack size of </param>
|
||||
/// <param name="amount"> How much to deduct from offers stack size </param>
|
||||
public void ReduceOfferQuantity(string offerId, int amount)
|
||||
{
|
||||
var offer = ragfairOfferHolder.GetOfferById(offerId);
|
||||
@@ -99,11 +99,11 @@ public class RagfairOfferService(
|
||||
ragfairOfferHolder.RemoveAllOffersByTrader(traderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the trader offers on flea need to be refreshed
|
||||
* @param traderID Trader to check
|
||||
* @returns true if they do
|
||||
*/
|
||||
/// <summary>
|
||||
/// Do the trader offers on flea need to be refreshed
|
||||
/// </summary>
|
||||
/// <param name="traderID"> Trader to check </param>
|
||||
/// <returns> True if they do </returns>
|
||||
public bool TraderOffersNeedRefreshing(string traderID)
|
||||
{
|
||||
var trader = databaseService.GetTrader(traderID);
|
||||
@@ -153,11 +153,10 @@ public class RagfairOfferService(
|
||||
ragfairOfferHolder.ResetExpiredOfferIds();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove stale offer from flea
|
||||
* @param staleOffer Stale offer to process
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove stale offer from flea
|
||||
/// </summary>
|
||||
/// <param name="staleOffer"> Stale offer to process </param>
|
||||
protected void ProcessStaleOffer(RagfairOffer staleOffer)
|
||||
{
|
||||
var staleOfferId = staleOffer.Id;
|
||||
@@ -243,13 +242,13 @@ public class RagfairOfferService(
|
||||
profile.RagfairInfo.Offers.Splice(offerinProfileIndex, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flea offer items are stacked up often beyond the StackMaxSize limit
|
||||
* Un stack the items into an array of root items and their children
|
||||
* Will create new items equal to the
|
||||
* @param items Offer items to unstack
|
||||
* @returns Unstacked array of items
|
||||
*/
|
||||
/// <summary>
|
||||
/// Flea offer items are stacked up often beyond the StackMaxSize limit.
|
||||
/// Unstack the items into an array of root items and their children.
|
||||
/// Will create new items equal to the stack.
|
||||
/// </summary>
|
||||
/// <param name="items"> Offer items to unstack </param>
|
||||
/// <returns> Unstacked array of items </returns>
|
||||
protected List<Item> UnstackOfferItems(List<Item> items)
|
||||
{
|
||||
var result = new List<Item>();
|
||||
|
||||
@@ -12,6 +12,9 @@ using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Stores flea prices for items as well as methods to interact with them.
|
||||
/// </summary>
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class RagfairPriceService(
|
||||
ISptLogger<RagfairPriceService> _logger,
|
||||
@@ -112,11 +115,11 @@ public class RagfairPriceService(
|
||||
return offerItems.Sum(item => GetFleaPriceForItem(item.Template));
|
||||
}
|
||||
|
||||
/**
|
||||
* get the dynamic (flea) price for an item
|
||||
* @param itemTpl item template id to look up
|
||||
* @returns price in roubles
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the dynamic (flea) price for an item
|
||||
/// </summary>
|
||||
/// <param name="itemTpl"> Item template id to look up </param>
|
||||
/// <returns> Price in roubles </returns>
|
||||
public double? GetDynamicPriceForItem(string itemTpl)
|
||||
{
|
||||
_databaseService.GetPrices().TryGetValue(itemTpl, out var value);
|
||||
|
||||
@@ -37,16 +37,16 @@ public class RagfairTaxService(
|
||||
return _playerOfferTaxCache[offerIdToGet];
|
||||
}
|
||||
|
||||
/**
|
||||
* // This method, along with CalculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice".
|
||||
* // It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary.
|
||||
* * @param item Item being sold on flea
|
||||
* * @param pmcData player profile
|
||||
* * @param requirementsValue
|
||||
* * @param offerItemCount Number of offers being created
|
||||
* * @param sellInOnePiece
|
||||
* * @returns Tax in roubles
|
||||
*/
|
||||
/// <summary>
|
||||
/// This method, along with CalculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice".
|
||||
/// It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary.
|
||||
/// </summary>
|
||||
/// <param name="item"> Item being sold on flea </param>
|
||||
/// <param name="pmcData"> Player profile </param>
|
||||
/// <param name="requirementsValue"></param>
|
||||
/// <param name="offerItemCount"> Number of offers being created </param>
|
||||
/// <param name="sellInOnePiece"></param>
|
||||
/// <returns> Tax in roubles </returns>
|
||||
public double CalculateTax(
|
||||
Item item,
|
||||
PmcData pmcData,
|
||||
@@ -127,8 +127,16 @@ public class RagfairTaxService(
|
||||
return taxValue;
|
||||
}
|
||||
|
||||
// This method is trying to replicate the item worth calculation method found in the client code.
|
||||
// Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring.
|
||||
/// <summary>
|
||||
/// This method is trying to replicate the item worth calculation method found in the client code.
|
||||
/// Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="itemTemplate"></param>
|
||||
/// <param name="itemCount"></param>
|
||||
/// <param name="pmcData"></param>
|
||||
/// <param name="isRootItem"></param>
|
||||
/// <returns></returns>
|
||||
protected double CalculateItemWorth(
|
||||
Item item,
|
||||
TemplateItem itemTemplate,
|
||||
|
||||
@@ -20,12 +20,12 @@ public class TraderPurchasePersisterService(
|
||||
{
|
||||
protected TraderConfig _traderConfig = _configServer.GetConfig<TraderConfig>();
|
||||
|
||||
/**
|
||||
* Get the purchases made from a trader for this profile before the last trader reset
|
||||
* @param sessionId Session id
|
||||
* @param traderId Trader to loop up purchases for
|
||||
* @returns Dictionary of assort id and count purchased
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get the purchases made from a trader for this profile before the last trader reset
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session id </param>
|
||||
/// <param name="traderId"> Trader to loop up purchases for </param>
|
||||
/// <returns> Dictionary of assort id and count purchased </returns>
|
||||
public Dictionary<string, TraderPurchaseData>? GetProfileTraderPurchases(string sessionId, string traderId)
|
||||
{
|
||||
var profile = _profileHelper.GetFullProfile(sessionId);
|
||||
@@ -43,13 +43,13 @@ public class TraderPurchasePersisterService(
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a purchase made from a trader for requested profile before the last trader reset
|
||||
* @param sessionId Session id
|
||||
* @param traderId Trader to loop up purchases for
|
||||
* @param assortId Id of assort to get data for
|
||||
* @returns TraderPurchaseData
|
||||
*/
|
||||
/// <summary>
|
||||
/// Get a purchase made from a trader for requested profile before the last trader reset
|
||||
/// </summary>
|
||||
/// <param name="sessionId"> Session ID </param>
|
||||
/// <param name="traderId"> Trader to loop up purchases for </param>
|
||||
/// <param name="assortId"> ID of assort to get data for </param>
|
||||
/// <returns> TraderPurchaseData </returns>
|
||||
public TraderPurchaseData? GetProfileTraderPurchase(
|
||||
string sessionId,
|
||||
string traderId,
|
||||
@@ -77,10 +77,10 @@ public class TraderPurchasePersisterService(
|
||||
return traderPurchases[assortId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all trader purchase records from all profiles that exist
|
||||
* @param traderId Traders id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Remove all trader purchase records from all profiles that exist
|
||||
/// </summary>
|
||||
/// <param name="traderId"> Traders ID </param>
|
||||
public void ResetTraderPurchasesStoredInProfile(string traderId)
|
||||
{
|
||||
// Reset all profiles purchase dictionaries now a trader update has occured;
|
||||
@@ -105,10 +105,10 @@ public class TraderPurchasePersisterService(
|
||||
_logger.Debug($"Reset trader: {traderId} assort buy limits");
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all server profiles and remove specific trader purchase data that has passed the trader refresh time
|
||||
* @param traderId Trader id
|
||||
*/
|
||||
/// <summary>
|
||||
/// Iterate over all server profiles and remove specific trader purchase data that has passed the trader refresh time
|
||||
/// </summary>
|
||||
/// <param name="traderId"> Trader ID </param>
|
||||
public void RemoveStalePurchasesFromProfiles(string traderId)
|
||||
{
|
||||
var profiles = _profileHelper.GetProfiles();
|
||||
|
||||
Reference in New Issue
Block a user