Merge pull request #372 from hulkhan22/feat/configurable-btr-delivery-time
feat: Configurable BTR delivery time
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"returnTimeOverrideSeconds": 0,
|
||||
"runIntervalSeconds": 30
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using SPTarkov.DI.Annotations;
|
||||
using SPTarkov.Server.Core.DI;
|
||||
using SPTarkov.Server.Core.Helpers;
|
||||
using SPTarkov.Server.Core.Models.Eft.Profile;
|
||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
||||
using SPTarkov.Server.Core.Models.Utils;
|
||||
using SPTarkov.Server.Core.Servers;
|
||||
using SPTarkov.Server.Core.Services;
|
||||
using SPTarkov.Server.Core.Utils;
|
||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||
|
||||
namespace SPTarkov.Server.Core.Callbacks;
|
||||
|
||||
[Injectable(TypePriority = OnUpdateOrder.BtrDeliveryCallbacks)]
|
||||
public class BtrDeliveryCallbacks(
|
||||
ISptLogger<BtrDeliveryCallbacks> _logger,
|
||||
BtrDeliveryService _btrDeliveryService,
|
||||
TimeUtil _timeUtil,
|
||||
ConfigServer _configServer,
|
||||
SaveServer _saveServer,
|
||||
HashUtil _hashUtil,
|
||||
ItemHelper _itemHelper
|
||||
)
|
||||
: IOnUpdate
|
||||
{
|
||||
private readonly BtrDeliveryConfig _btrDeliveryConfig = _configServer.GetConfig<BtrDeliveryConfig>();
|
||||
|
||||
public Task<bool> OnUpdate(long secondsSinceLastRun)
|
||||
{
|
||||
if (secondsSinceLastRun < _btrDeliveryConfig.RunIntervalSeconds)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
ProcessDeliveries();
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process BTR delivery items of all profiles prior to being given back to the player through the mail service
|
||||
/// </summary>
|
||||
protected void ProcessDeliveries()
|
||||
{
|
||||
// Process each installed profile.
|
||||
foreach (var sessionId in _saveServer.GetProfiles())
|
||||
{
|
||||
ProcessDeliveryByProfile(sessionId.Key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process delivery items of a single profile prior to being given back to the player through the mail service
|
||||
/// </summary>
|
||||
/// <param name="sessionId">Player id</param>
|
||||
public void ProcessDeliveryByProfile(string sessionId)
|
||||
{
|
||||
// Filter out items that don't need to be processed yet.
|
||||
var toBeProcessed = FilterDeliveryItems(sessionId);
|
||||
|
||||
// Do nothing if no items to process
|
||||
if (toBeProcessed.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessDeliveryItems(toBeProcessed, sessionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all delivery items that are ready to be processed in a specific profile
|
||||
/// </summary>
|
||||
/// <param name="sessionId">Session/Player id</param>
|
||||
/// <returns>All delivery items that are ready to be processed</returns>
|
||||
protected List<BtrDelivery> FilterDeliveryItems(string sessionId)
|
||||
{
|
||||
var currentTime = _timeUtil.GetTimeStamp();
|
||||
|
||||
var deliveryList = _saveServer.GetProfile(sessionId).BtrDeliveryList;
|
||||
if (deliveryList != null && deliveryList!.Count > 0)
|
||||
{
|
||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
_logger.Debug($"Found {deliveryList.Count} BTR delivery package(s) in profile {sessionId}");
|
||||
}
|
||||
return deliveryList.Where(toBeDelivered => currentTime >= toBeDelivered.ScheduledTime).ToList();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method orchestrates the processing of delivery items in a profile
|
||||
/// </summary>
|
||||
/// <param name="packagesToBeDelivered">The delivery items to process</param>
|
||||
/// <param name="sessionId">session ID that should receive the processed items</param>
|
||||
protected void ProcessDeliveryItems(List<BtrDelivery> packagesToBeDelivered, string sessionId)
|
||||
{
|
||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
_logger.Debug(
|
||||
$"Processing {packagesToBeDelivered.Count} BTR delivery package(s), which include a total of: {packagesToBeDelivered.Select(items => items.Items).Count()} items, in profile: {sessionId}"
|
||||
);
|
||||
}
|
||||
|
||||
// Iterate over each of the insurance packages.
|
||||
foreach (var package in packagesToBeDelivered)
|
||||
{
|
||||
// Create a new root parent ID for the message we'll be sending the player
|
||||
var rootItemParentId = _hashUtil.Generate();
|
||||
|
||||
// Update the delivery items to have the new root parent ID for root/orphaned items
|
||||
package.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, package.Items);
|
||||
|
||||
_btrDeliveryService.SendBTRDelivery(sessionId, package.Items);
|
||||
|
||||
// Remove the fully processed BTR delivery package from the profile.
|
||||
_btrDeliveryService.RemoveBTRDeliveryPackageFromProfile(sessionId, package);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,5 @@ public static class OnUpdateOrder
|
||||
public const int DialogueCallbacks = 1000;
|
||||
public const int HideoutCallbacks = 2000;
|
||||
public const int InsuranceCallbacks = 3000;
|
||||
public const int BtrDeliveryCallbacks = 4000;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ public record SptProfile
|
||||
set;
|
||||
}
|
||||
|
||||
[JsonPropertyName("btrDelivery")]
|
||||
public List<BtrDelivery>? BtrDeliveryList
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assort purchases made by player since last trader refresh
|
||||
/// </summary>
|
||||
@@ -1056,3 +1063,30 @@ public record Insurance
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public record BtrDelivery
|
||||
{
|
||||
[JsonExtensionData]
|
||||
public Dictionary<string, object> ExtensionData { get; set; }
|
||||
|
||||
[JsonPropertyName("_id")]
|
||||
public string? Id
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[JsonPropertyName("scheduledTime")]
|
||||
public int? ScheduledTime
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[JsonPropertyName("items")]
|
||||
public List<Item>? Items
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ public static class ConfigTypesExtension
|
||||
ConfigTypes.AIRDROP => "spt-airdrop",
|
||||
ConfigTypes.BACKUP => "spt-backup",
|
||||
ConfigTypes.BOT => "spt-bot",
|
||||
ConfigTypes.BTR_DELIVERY => "spt-btrdelivery",
|
||||
ConfigTypes.PMC => "spt-pmc",
|
||||
ConfigTypes.CORE => "spt-core",
|
||||
ConfigTypes.HEALTH => "spt-health",
|
||||
@@ -46,6 +47,7 @@ public static class ConfigTypesExtension
|
||||
ConfigTypes.AIRDROP => typeof(AirdropConfig),
|
||||
ConfigTypes.BACKUP => typeof(BackupConfig),
|
||||
ConfigTypes.BOT => typeof(BotConfig),
|
||||
ConfigTypes.BTR_DELIVERY => typeof(BtrDeliveryConfig),
|
||||
ConfigTypes.PMC => typeof(PmcConfig),
|
||||
ConfigTypes.CORE => typeof(CoreConfig),
|
||||
ConfigTypes.HEALTH => typeof(HealthConfig),
|
||||
@@ -80,6 +82,7 @@ public enum ConfigTypes
|
||||
AIRDROP,
|
||||
BACKUP,
|
||||
BOT,
|
||||
BTR_DELIVERY,
|
||||
PMC,
|
||||
CORE,
|
||||
HEALTH,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPTarkov.Server.Core.Models.Spt.Config;
|
||||
|
||||
public record BtrDeliveryConfig : BaseConfig
|
||||
{
|
||||
[JsonPropertyName("kind")]
|
||||
public override string Kind
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = "spt-btrdelivery";
|
||||
|
||||
/// <summary>
|
||||
/// Override to control how quickly delivery is processed/returned in seconds
|
||||
/// </summary>
|
||||
[JsonPropertyName("returnTimeOverrideSeconds")]
|
||||
public double ReturnTimeOverrideSeconds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How often server should process BTR delivery in seconds
|
||||
/// </summary>
|
||||
[JsonPropertyName("runIntervalSeconds")]
|
||||
public double RunIntervalSeconds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using SPTarkov.DI.Annotations;
|
||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||
using SPTarkov.Server.Core.Models.Eft.Match;
|
||||
using SPTarkov.Server.Core.Models.Eft.Profile;
|
||||
using SPTarkov.Server.Core.Models.Enums;
|
||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
||||
using SPTarkov.Server.Core.Models.Utils;
|
||||
using SPTarkov.Server.Core.Servers;
|
||||
using SPTarkov.Server.Core.Utils;
|
||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||
|
||||
namespace SPTarkov.Server.Core.Services;
|
||||
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class BtrDeliveryService(
|
||||
ISptLogger<BtrDeliveryService> _logger,
|
||||
DatabaseService _databaseService,
|
||||
RandomUtil _randomUtil,
|
||||
HashUtil _hashUtil,
|
||||
TimeUtil _timeUtil,
|
||||
SaveServer _saveServer,
|
||||
MailSendService _mailSendService,
|
||||
ConfigServer _configServer,
|
||||
LocalisationService _localisationService
|
||||
)
|
||||
{
|
||||
protected BtrDeliveryConfig _btrDeliveryConfig = _configServer.GetConfig<BtrDeliveryConfig>();
|
||||
protected TraderConfig _traderConfig = _configServer.GetConfig<TraderConfig>();
|
||||
|
||||
protected static List<string> _transferTypes = new()
|
||||
{
|
||||
"btr",
|
||||
"transit"
|
||||
};
|
||||
|
||||
/// <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>
|
||||
public void HandleItemTransferEvent(string sessionId, EndLocalRaidRequestData request)
|
||||
{
|
||||
foreach (var transferType in _transferTypes)
|
||||
{
|
||||
var rootId = $"{Traders.BTR}_{transferType}";
|
||||
List<Item>? itemsToSend = null;
|
||||
|
||||
// if rootId doesnt exist in TransferItems, skip
|
||||
if (!request?.TransferItems?.TryGetValue(rootId, out itemsToSend) ?? false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter out the btr container item from transferred items before delivering
|
||||
itemsToSend = itemsToSend?.Where(item => item.Id != Traders.BTR).ToList();
|
||||
if (itemsToSend?.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HandleTransferItemDelivery(sessionId, itemsToSend);
|
||||
}
|
||||
}
|
||||
|
||||
protected void HandleTransferItemDelivery(string sessionId, List<Item> items)
|
||||
{
|
||||
var serverProfile = _saveServer.GetProfile(sessionId);
|
||||
var pmcData = serverProfile.CharacterData.PmcData;
|
||||
|
||||
// Remove any items that were returned by the item delivery, but also insured, from the player's insurance list
|
||||
// This is to stop items being duplicated by being returned from both item delivery and insurance
|
||||
var deliveredItemIds = items.Select(item => item.Id);
|
||||
pmcData.InsuredItems = pmcData.InsuredItems
|
||||
.Where(insuredItem => !deliveredItemIds.Contains(insuredItem.ItemId))
|
||||
.ToList();
|
||||
|
||||
if (_saveServer.GetProfile(sessionId).BtrDeliveryList == null)
|
||||
{
|
||||
_saveServer.GetProfile(sessionId).BtrDeliveryList = new List<BtrDelivery>();
|
||||
}
|
||||
|
||||
// Store delivery to send to player later in profile
|
||||
_saveServer.GetProfile(sessionId).BtrDeliveryList.Add(
|
||||
new BtrDelivery
|
||||
{
|
||||
Id = _hashUtil.Generate(),
|
||||
ScheduledTime = (int) GetBTRDeliveryReturnTimestamp(),
|
||||
Items = items
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void SendBTRDelivery(string sessionId, List<Item> items)
|
||||
{
|
||||
var dialogueTemplates = _databaseService.GetTrader(Traders.BTR).Dialogue;
|
||||
if (dialogueTemplates is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("inraid-unable_to_deliver_item_no_trader_found", Traders.BTR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dialogueTemplates.TryGetValue("itemsDelivered", out var itemsDelivered))
|
||||
{
|
||||
_logger.Error("dialogueTemplates doesn't contain itemsDelivered");
|
||||
return;
|
||||
}
|
||||
|
||||
var messageId = _randomUtil.GetArrayValue(itemsDelivered);
|
||||
var messageStoreTime = _timeUtil.GetHoursAsSeconds(_traderConfig.Fence.BtrDeliveryExpireHours);
|
||||
|
||||
// Send the items to the player
|
||||
_mailSendService.SendLocalisedNpcMessageToPlayer(
|
||||
sessionId,
|
||||
Traders.BTR,
|
||||
MessageType.BtrItemsDelivery,
|
||||
messageId,
|
||||
items,
|
||||
messageStoreTime
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a BTR delivery package from a profile using the package's ID.
|
||||
/// </summary>
|
||||
/// <param name="sessionId">The session ID of the profile to remove the package from.</param>
|
||||
/// <param name="delivery">The BTR delivery package to remove.</param>
|
||||
public void RemoveBTRDeliveryPackageFromProfile(string sessionId, BtrDelivery delivery)
|
||||
{
|
||||
var profile = _saveServer.GetProfile(sessionId);
|
||||
profile.BtrDeliveryList = profile.BtrDeliveryList
|
||||
.Where(package => package.Id != delivery.Id)
|
||||
.ToList();
|
||||
|
||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
_logger.Debug($"Removed processed BTR delivery package. Remaining packages: {profile.BtrDeliveryList.Count}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a timestamp of when items given to the BTR driver should be sent to player.
|
||||
/// </summary>
|
||||
/// <returns>Timestamp to return items to player in seconds</returns>
|
||||
protected double GetBTRDeliveryReturnTimestamp()
|
||||
{
|
||||
// If override in config is non-zero, use that
|
||||
if (_btrDeliveryConfig.ReturnTimeOverrideSeconds > 0)
|
||||
{
|
||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
_logger.Debug($"BTR delivery override used: returning in {_btrDeliveryConfig.ReturnTimeOverrideSeconds} seconds");
|
||||
}
|
||||
|
||||
return _timeUtil.GetTimeStamp() + _btrDeliveryConfig.ReturnTimeOverrideSeconds;
|
||||
}
|
||||
|
||||
return _timeUtil.GetTimeStamp();
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,7 @@ public class CreateProfileService(
|
||||
VitalityData = new Vitality(),
|
||||
InraidData = new Inraid(),
|
||||
InsuranceList = [],
|
||||
BtrDeliveryList = [],
|
||||
TraderPurchases = new Dictionary<string, Dictionary<string, TraderPurchaseData>?>(),
|
||||
FriendProfileIds = [],
|
||||
CustomisationUnlocks = []
|
||||
|
||||
@@ -8,7 +8,6 @@ using SPTarkov.Server.Core.Models.Eft.Profile;
|
||||
using SPTarkov.Server.Core.Models.Eft.Quests;
|
||||
using SPTarkov.Server.Core.Models.Enums;
|
||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
||||
using SPTarkov.Server.Core.Models.Spt.Location;
|
||||
using SPTarkov.Server.Core.Models.Utils;
|
||||
using SPTarkov.Server.Core.Servers;
|
||||
using SPTarkov.Server.Core.Utils;
|
||||
@@ -54,6 +53,7 @@ public class LocationLifecycleService
|
||||
protected TimeUtil _timeUtil;
|
||||
protected TraderConfig _traderConfig;
|
||||
protected TraderHelper _traderHelper;
|
||||
protected BtrDeliveryService _btrDeliveryService;
|
||||
|
||||
public LocationLifecycleService(
|
||||
ISptLogger<LocationLifecycleService> logger,
|
||||
@@ -83,7 +83,8 @@ public class LocationLifecycleService
|
||||
PmcWaveGenerator pmcWaveGenerator,
|
||||
QuestHelper questHelper,
|
||||
InsuranceService insuranceService,
|
||||
MatchBotDetailsCacheService matchBotDetailsCacheService
|
||||
MatchBotDetailsCacheService matchBotDetailsCacheService,
|
||||
BtrDeliveryService btrDeliveryService
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -114,6 +115,7 @@ public class LocationLifecycleService
|
||||
_questHelper = questHelper;
|
||||
_insuranceService = insuranceService;
|
||||
_matchBotDetailsCacheService = matchBotDetailsCacheService;
|
||||
_btrDeliveryService = btrDeliveryService;
|
||||
|
||||
_locationConfig = _configServer.GetConfig<LocationConfig>();
|
||||
_inRaidConfig = _configServer.GetConfig<InRaidConfig>();
|
||||
@@ -442,7 +444,7 @@ public class LocationLifecycleService
|
||||
var isSurvived = IsPlayerSurvived(request.Results);
|
||||
|
||||
// Handle items transferred via BTR or transit to player mailbox
|
||||
HandleItemTransferEvent(sessionId, request);
|
||||
_btrDeliveryService.HandleItemTransferEvent(sessionId, request);
|
||||
|
||||
// Player is moving between maps
|
||||
if (isTransfer && request.LocationTransit is not null)
|
||||
@@ -458,7 +460,6 @@ public class LocationLifecycleService
|
||||
if (!isPmc)
|
||||
{
|
||||
HandlePostRaidPlayerScav(sessionId, pmcProfile, scavProfile, isDead, isTransfer, isSurvived, request);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -695,7 +696,7 @@ public class LocationLifecycleService
|
||||
{
|
||||
_logger.Error($"post raid fence data not found for: {sessionId}");
|
||||
}
|
||||
|
||||
|
||||
scavProfile.TradersInfo[Traders.FENCE].Standing = Math.Min(Math.Max(postRaidFenceData.Standing.Value, fenceMin), fenceMax);
|
||||
|
||||
// Successful extract as scav, give some rep
|
||||
@@ -1076,81 +1077,6 @@ public class LocationLifecycleService
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
{
|
||||
"btr",
|
||||
"transit"
|
||||
};
|
||||
|
||||
foreach (var trasferType in transferTypes)
|
||||
{
|
||||
var rootId = $"{Traders.BTR}_{trasferType}";
|
||||
List<Item>? itemsToSend = null;
|
||||
|
||||
// if rootId doesnt exist in TransferItems, skip
|
||||
if (!request?.TransferItems?.TryGetValue(rootId, out itemsToSend) ?? false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter out the btr container item from transferred items before delivering
|
||||
itemsToSend = itemsToSend?.Where(item => item.Id != Traders.BTR).ToList();
|
||||
if (itemsToSend?.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TransferItemDelivery(sessionId, Traders.BTR, itemsToSend);
|
||||
}
|
||||
}
|
||||
|
||||
protected void TransferItemDelivery(string sessionId, string traderId, List<Item> items)
|
||||
{
|
||||
var serverProfile = _saveServer.GetProfile(sessionId);
|
||||
var pmcData = serverProfile.CharacterData.PmcData;
|
||||
|
||||
var dialogueTemplates = _databaseService.GetTrader(traderId).Dialogue;
|
||||
if (dialogueTemplates is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("inraid-unable_to_deliver_item_no_trader_found", traderId));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dialogueTemplates.TryGetValue("itemsDelivered", out var itemsDelivered))
|
||||
{
|
||||
_logger.Error("dialogueTemplates doesn't contain itemsDelivered");
|
||||
return;
|
||||
}
|
||||
|
||||
var messageId = _randomUtil.GetArrayValue(itemsDelivered);
|
||||
var messageStoreTime = _timeUtil.GetHoursAsSeconds(_traderConfig.Fence.BtrDeliveryExpireHours);
|
||||
|
||||
// Remove any items that were returned by the item delivery, but also insured, from the player's insurance list
|
||||
// This is to stop items being duplicated by being returned from both item delivery and insurance
|
||||
var deliveredItemIds = items.Select(item => item.Id);
|
||||
pmcData.InsuredItems = pmcData.InsuredItems.Where(insuredItem => !deliveredItemIds.Contains(insuredItem.ItemId)
|
||||
)
|
||||
.ToList();
|
||||
|
||||
// Send the items to the player
|
||||
_mailSendService.SendLocalisedNpcMessageToPlayer(
|
||||
sessionId,
|
||||
traderId,
|
||||
MessageType.BtrItemsDelivery,
|
||||
messageId,
|
||||
items,
|
||||
messageStoreTime
|
||||
);
|
||||
}
|
||||
|
||||
protected void HandleInsuredItemLostEvent(
|
||||
string sessionId,
|
||||
PmcData preRaidPmcProfile,
|
||||
|
||||
Reference in New Issue
Block a user