implement services
This commit is contained in:
+140
-12
@@ -2,7 +2,9 @@ using Core.Annotations;
|
||||
using Core.Helpers;
|
||||
using Core.Models.Enums;
|
||||
using Core.Models.Spt.Config;
|
||||
using Core.Models.Spt.Dialog;
|
||||
using Core.Servers;
|
||||
using Core.Utils;
|
||||
using ILogger = Core.Models.Utils.ILogger;
|
||||
|
||||
namespace Core.Services;
|
||||
@@ -11,18 +13,34 @@ namespace Core.Services;
|
||||
public class GiftService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly ConfigServer _configServer;
|
||||
|
||||
private readonly MailSendService _mailSendService;
|
||||
private readonly LocalisationService _localisationService;
|
||||
private readonly HashUtil _hashUtil;
|
||||
private readonly TimeUtil _timeUtil;
|
||||
private readonly ProfileHelper _profileHelper;
|
||||
private readonly ConfigServer _configServer;
|
||||
|
||||
private readonly GiftsConfig _giftConfig;
|
||||
|
||||
public GiftService(
|
||||
public GiftService
|
||||
(
|
||||
ILogger logger,
|
||||
ConfigServer configServer,
|
||||
ProfileHelper profileHelper)
|
||||
MailSendService mailSendService,
|
||||
LocalisationService localisationService,
|
||||
HashUtil hashUtil,
|
||||
TimeUtil timeUtil,
|
||||
ProfileHelper profileHelper,
|
||||
ConfigServer configServer
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_configServer = configServer;
|
||||
_mailSendService = mailSendService;
|
||||
_localisationService = localisationService;
|
||||
_hashUtil = hashUtil;
|
||||
_timeUtil = timeUtil;
|
||||
_profileHelper = profileHelper;
|
||||
_configServer = configServer;
|
||||
|
||||
_giftConfig = _configServer.GetConfig<GiftsConfig>(ConfigTypes.GIFTS);
|
||||
}
|
||||
@@ -34,7 +52,7 @@ public class GiftService
|
||||
*/
|
||||
public bool GiftExists(string giftId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _giftConfig.Gifts[giftId] is not null;
|
||||
}
|
||||
|
||||
public Gift GetGiftById(string giftId)
|
||||
@@ -50,7 +68,7 @@ public class GiftService
|
||||
*/
|
||||
public Dictionary<string, Gift> GetGifts()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _giftConfig.Gifts;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +77,7 @@ public class GiftService
|
||||
*/
|
||||
public List<string> GetGiftIds()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _giftConfig.Gifts.Keys.ToList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +108,96 @@ public class GiftService
|
||||
_logger.Warning($"Gift {giftId} has items but no collection time limit, defaulting to 48 hours");
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
// Handle system messsages
|
||||
if (giftData.Sender == GiftSenderType.System)
|
||||
{
|
||||
// Has a localisable text id to send to player
|
||||
if (giftData.LocaleTextId is not null)
|
||||
{
|
||||
_mailSendService.SendLocalisedSystemMessageToPlayer(
|
||||
playerId,
|
||||
giftData.LocaleTextId,
|
||||
giftData.Items,
|
||||
giftData.ProfileChangeEvents,
|
||||
_timeUtil.GetHoursAsSeconds(giftData.CollectionTimeHours ?? 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
_mailSendService.SendSystemMessageToPlayer(
|
||||
playerId,
|
||||
giftData.MessageText,
|
||||
giftData.Items,
|
||||
_timeUtil.GetHoursAsSeconds(giftData.CollectionTimeHours ?? 1),
|
||||
giftData.ProfileChangeEvents);
|
||||
}
|
||||
}
|
||||
// Handle user messages
|
||||
else if (giftData.Sender == GiftSenderType.User)
|
||||
{
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
playerId,
|
||||
giftData.SenderDetails,
|
||||
giftData.MessageText,
|
||||
giftData.Items,
|
||||
_timeUtil.GetHoursAsSeconds(giftData.CollectionTimeHours ?? 1));
|
||||
}
|
||||
else if (giftData.Sender == GiftSenderType.Trader)
|
||||
{
|
||||
if (giftData.LocaleTextId is not null)
|
||||
{
|
||||
_mailSendService.SendLocalisedNpcMessageToPlayer(
|
||||
playerId,
|
||||
giftData.Trader,
|
||||
MessageType.MESSAGE_WITH_ITEMS,
|
||||
giftData.LocaleTextId,
|
||||
giftData.Items,
|
||||
_timeUtil.GetHoursAsSeconds(giftData.CollectionTimeHours ?? 1),
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mailSendService.SendLocalisedNpcMessageToPlayer(
|
||||
playerId,
|
||||
giftData.Trader,
|
||||
MessageType.MESSAGE_WITH_ITEMS,
|
||||
giftData.MessageText,
|
||||
giftData.Items,
|
||||
_timeUtil.GetHoursAsSeconds(giftData.CollectionTimeHours ?? 1),
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: further split out into different message systems like above SYSTEM method
|
||||
// Trader / ragfair
|
||||
SendMessageDetails details = new () {
|
||||
RecipientId = playerId,
|
||||
Sender = GetMessageType(giftData),
|
||||
SenderDetails = new ()
|
||||
{
|
||||
Id = GetSenderId(giftData),
|
||||
Aid = 1234567, // TODO - pass proper aid value
|
||||
Info = null,
|
||||
},
|
||||
MessageText = giftData.MessageText,
|
||||
Items = giftData.Items,
|
||||
ItemsMaxStorageLifetimeSeconds = _timeUtil.GetHoursAsSeconds(giftData.CollectionTimeHours ?? 0),
|
||||
};
|
||||
|
||||
if (giftData.Trader is not null) {
|
||||
details.Trader = giftData.Trader;
|
||||
}
|
||||
|
||||
_mailSendService.SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
_profileHelper.FlagGiftReceivedInProfile(playerId, giftId, maxGiftsToSendCount);
|
||||
|
||||
return GiftSentResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,9 +205,19 @@ public class GiftService
|
||||
* @param giftData Gift to send player
|
||||
* @returns trader/user/system id
|
||||
*/
|
||||
protected string? GetSenderId(Gift giftData)
|
||||
private string? GetSenderId(Gift giftData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (giftData.Sender == GiftSenderType.Trader)
|
||||
{
|
||||
return Enum.GetName(typeof(GiftSenderType), giftData.Sender);
|
||||
}
|
||||
|
||||
if (giftData.Sender == GiftSenderType.User)
|
||||
{
|
||||
return giftData.Sender.ToString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +227,18 @@ public class GiftService
|
||||
*/
|
||||
protected MessageType? GetMessageType(Gift giftData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
switch (giftData.Sender)
|
||||
{
|
||||
case GiftSenderType.System:
|
||||
return MessageType.SYSTEM_MESSAGE;
|
||||
case GiftSenderType.Trader:
|
||||
return MessageType.NPC_TRADER;
|
||||
case GiftSenderType.User:
|
||||
return MessageType.USER_MESSAGE;
|
||||
default:
|
||||
_logger.Error(_localisationService.GetText("gift-unable_to_handle_message_type_command", giftData.Sender));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,560 @@
|
||||
using Core.Annotations;
|
||||
using Core.Helpers;
|
||||
using Core.Models.Eft.Common.Tables;
|
||||
using Core.Models.Eft.Profile;
|
||||
using Core.Models.Enums;
|
||||
using Core.Models.Spt.Dialog;
|
||||
using Core.Servers;
|
||||
using Core.Utils;
|
||||
using ILogger = Core.Models.Utils.ILogger;
|
||||
|
||||
namespace Core.Services;
|
||||
|
||||
[Injectable]
|
||||
public class MailSendService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly HashUtil _hashUtil;
|
||||
private readonly TimeUtil _timeUtil;
|
||||
private readonly SaveServer _saveServer;
|
||||
private readonly DatabaseService _databaseService;
|
||||
private readonly NotifierHelper _notifierHelper;
|
||||
private readonly DialogueHelper _dialogueHelper;
|
||||
private readonly NotificationSendHelper _notificationSendHelper;
|
||||
private readonly LocalisationService _localisationService;
|
||||
private readonly ItemHelper _itemHelper;
|
||||
private readonly TraderHelper _traderHelper;
|
||||
|
||||
private const string _systemSenderId = "59e7125688a45068a6249071";
|
||||
private readonly List<MessageType> _messageTypes = [MessageType.NPC_TRADER, MessageType.FLEAMARKET_MESSAGE];
|
||||
private readonly List<string> _slotNames = ["hideout", "main"];
|
||||
|
||||
public MailSendService
|
||||
(
|
||||
ILogger logger,
|
||||
HashUtil hashUtil,
|
||||
TimeUtil timeUtil,
|
||||
SaveServer saveServer,
|
||||
DatabaseService databaseService,
|
||||
NotifierHelper notifierHelper,
|
||||
DialogueHelper dialogueHelper,
|
||||
NotificationSendHelper notificationSendHelper,
|
||||
LocalisationService localisationService,
|
||||
ItemHelper itemHelper,
|
||||
TraderHelper traderHelper
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_hashUtil = hashUtil;
|
||||
_timeUtil = timeUtil;
|
||||
_saveServer = saveServer;
|
||||
_databaseService = databaseService;
|
||||
_notifierHelper = notifierHelper;
|
||||
_dialogueHelper = dialogueHelper;
|
||||
_localisationService = localisationService;
|
||||
_itemHelper = itemHelper;
|
||||
_traderHelper = traderHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public void SendDirectNpcMessageToPlayer(
|
||||
string sessionId,
|
||||
string trader,
|
||||
MessageType messageType,
|
||||
string message,
|
||||
List<Item>? items,
|
||||
long? maxStorageTimeSeconds,
|
||||
SystemData? systemData,
|
||||
MessageContentRagfair? ragfair
|
||||
)
|
||||
{
|
||||
if (trader is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("mailsend-missing_trader", new
|
||||
{
|
||||
MessageType = messageType,
|
||||
SessionId = sessionId,
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessageDetails details = new()
|
||||
{
|
||||
RecipientId = sessionId,
|
||||
Sender = messageType,
|
||||
DialogType = MessageType.NPC_TRADER,
|
||||
Trader = trader,
|
||||
MessageText = message,
|
||||
};
|
||||
|
||||
// Add items to message
|
||||
if (items?.Count > 0)
|
||||
{
|
||||
details.Items.AddRange(items);
|
||||
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800;
|
||||
}
|
||||
|
||||
if (systemData is not null)
|
||||
details.SystemData = systemData;
|
||||
|
||||
if (ragfair is not null)
|
||||
details.RagfairDetails = ragfair;
|
||||
|
||||
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
|
||||
*/
|
||||
public void SendLocalisedNpcMessageToPlayer(
|
||||
string sessionId,
|
||||
string trader,
|
||||
MessageType messageType,
|
||||
string messageLocaleId,
|
||||
List<Item>? items,
|
||||
long? maxStorageTimeSeconds,
|
||||
SystemData? systemData,
|
||||
MessageContentRagfair? ragfair
|
||||
)
|
||||
{
|
||||
if (trader is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("mailsend-missing_trader", new
|
||||
{
|
||||
MessageType = messageType,
|
||||
SessionId = sessionId,
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessageDetails details = new()
|
||||
{
|
||||
RecipientId = sessionId,
|
||||
Sender = messageType,
|
||||
DialogType = MessageType.NPC_TRADER,
|
||||
Trader = trader,
|
||||
TemplateId = messageLocaleId,
|
||||
};
|
||||
|
||||
// add items to message
|
||||
|
||||
if (items?.Count > 0)
|
||||
{
|
||||
details.Items.AddRange(items);
|
||||
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800;
|
||||
}
|
||||
|
||||
if (systemData is not null)
|
||||
details.SystemData = systemData;
|
||||
|
||||
if (ragfair is not null)
|
||||
details.RagfairDetails = ragfair;
|
||||
|
||||
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
|
||||
*/
|
||||
public void SendSystemMessageToPlayer(
|
||||
string sessionId,
|
||||
string message,
|
||||
List<Item>? items,
|
||||
long? maxStorageTimeSeconds,
|
||||
List<ProfileChangeEvent>? profileChangeEvents)
|
||||
{
|
||||
SendMessageDetails details = new()
|
||||
{
|
||||
RecipientId = sessionId,
|
||||
Sender = MessageType.SYSTEM_MESSAGE,
|
||||
MessageText = message,
|
||||
};
|
||||
|
||||
// add items to message
|
||||
if (items?.Count > 0)
|
||||
{
|
||||
var rootItemParentId = _hashUtil.Generate();
|
||||
|
||||
details.Items.AddRange(_itemHelper.AdoptOrphanedItems(rootItemParentId, items));
|
||||
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800;
|
||||
}
|
||||
|
||||
if ((profileChangeEvents?.Count ?? 0) > 0)
|
||||
details.ProfileChangeEvents = profileChangeEvents;
|
||||
|
||||
SendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
public void SendLocalisedSystemMessageToPlayer(
|
||||
string sessionId,
|
||||
string messageLocaleId,
|
||||
List<Item>? items,
|
||||
List<ProfileChangeEvent>? profileChangeEvents,
|
||||
long? maxStorageTimeSeconds
|
||||
)
|
||||
{
|
||||
SendMessageDetails details = new()
|
||||
{
|
||||
RecipientId = sessionId,
|
||||
Sender = MessageType.SYSTEM_MESSAGE,
|
||||
TemplateId = messageLocaleId
|
||||
};
|
||||
|
||||
// add items to message
|
||||
if (items?.Count > 0)
|
||||
{
|
||||
details.Items.AddRange(items);
|
||||
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800;
|
||||
}
|
||||
|
||||
if ((profileChangeEvents?.Count ?? 0) > 0)
|
||||
details.ProfileChangeEvents = profileChangeEvents;
|
||||
|
||||
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
|
||||
*/
|
||||
public void SendUserMessageToPlayer(
|
||||
string sessionId,
|
||||
UserDialogInfo senderDetails,
|
||||
string message,
|
||||
List<Item>? items,
|
||||
long? maxStorageTimeSeconds
|
||||
)
|
||||
{
|
||||
SendMessageDetails details = new()
|
||||
{
|
||||
RecipientId = sessionId,
|
||||
Sender = MessageType.USER_MESSAGE,
|
||||
SenderDetails = senderDetails,
|
||||
MessageText = message
|
||||
};
|
||||
|
||||
// add items to message
|
||||
if (items?.Count > 0)
|
||||
{
|
||||
details.Items.AddRange(items);
|
||||
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
public void SendMessageToPlayer(SendMessageDetails messageDetails)
|
||||
{
|
||||
// Get dialog, create if doesn't exist
|
||||
var senderDialog = GetDialog(messageDetails);
|
||||
|
||||
// Flag dialog as containing a new message to player
|
||||
senderDialog.New++;
|
||||
|
||||
// Craft message
|
||||
var message = CreateDialogMessage(senderDialog.Id, messageDetails);
|
||||
|
||||
// Create items array
|
||||
// Generate item stash if we have rewards.
|
||||
var itemsToSendToPlayer = ProcessItemsBeforeAddingToMail(senderDialog.Type, messageDetails);
|
||||
|
||||
// If there's items to send to player, flag dialog as containing attachments
|
||||
if ((itemsToSendToPlayer.Data?.Count ?? 0) > 0)
|
||||
{
|
||||
senderDialog.AttachmentsNew += 1;
|
||||
}
|
||||
|
||||
// Store reward items inside message and set appropriate flags inside message
|
||||
AddRewardItemsToMessage(message, itemsToSendToPlayer, messageDetails.ItemsMaxStorageLifetimeSeconds);
|
||||
|
||||
if (messageDetails.ProfileChangeEvents is not null)
|
||||
message.ProfileChangeEvents = messageDetails.ProfileChangeEvents;
|
||||
|
||||
// Add message to dialog
|
||||
senderDialog.Messages.Add(message);
|
||||
|
||||
// TODO: clean up old code here
|
||||
// Offer Sold notifications are now separate from the main notification
|
||||
if (
|
||||
_messageTypes.Contains(senderDialog.Type ?? MessageType.SYSTEM_MESSAGE) &&
|
||||
messageDetails?.RagfairDetails is not null
|
||||
)
|
||||
{
|
||||
var offerSoldMessage = _notifierHelper.CreateRagfairOfferSoldNotification(
|
||||
message,
|
||||
messageDetails.RagfairDetails
|
||||
);
|
||||
_notificationSendHelper.SendMessage(messageDetails.RecipientId, offerSoldMessage);
|
||||
message.MessageType = MessageType.MESSAGE_WITH_ITEMS; // Should prevent getting the same notification popup twice
|
||||
}
|
||||
|
||||
// Send message off to player so they get it in client
|
||||
var notificationMessage = _notifierHelper.CreateNewMessageNotification(message);
|
||||
_notificationSendHelper.SendMessage(messageDetails.RecipientId, notificationMessage);
|
||||
}
|
||||
|
||||
public void SendPlayerMessageToNpc(string sessionId, string targetNpcId, string message)
|
||||
{
|
||||
var playerProfile = _saveServer.GetProfile(sessionId);
|
||||
var dialogWithNpc = playerProfile.DialogueRecords[targetNpcId];
|
||||
if (dialogWithNpc is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("mailsend-missing_npc_dialog", targetNpcId));
|
||||
return;
|
||||
}
|
||||
|
||||
dialogWithNpc.Messages.Add(new()
|
||||
{
|
||||
Id = _hashUtil.Generate(),
|
||||
DateTime = _timeUtil.GetTimeStamp(),
|
||||
HasRewards = false,
|
||||
UserId = playerProfile.CharacterData.PmcData.Id,
|
||||
MessageType = MessageType.USER_MESSAGE,
|
||||
RewardCollected = false,
|
||||
Text = message
|
||||
});
|
||||
}
|
||||
|
||||
private Message CreateDialogMessage(string dialogId, SendMessageDetails messageDetails)
|
||||
{
|
||||
Message message = new()
|
||||
{
|
||||
Id = _hashUtil.Generate(),
|
||||
UserId = dialogId,
|
||||
MessageType = messageDetails.DialogType,
|
||||
DateTime = _timeUtil.GetTimeStamp(),
|
||||
Text = (messageDetails.TemplateId is not null) ? "" : messageDetails.MessageText,
|
||||
TemplateId = messageDetails.TemplateId,
|
||||
HasRewards = false,
|
||||
RewardCollected = false,
|
||||
SystemData = messageDetails.SystemData is not null ? messageDetails.SystemData : null,
|
||||
ProfileChangeEvents = (messageDetails.ProfileChangeEvents?.Count == 0) ? messageDetails.ProfileChangeEvents : null
|
||||
};
|
||||
|
||||
// Clean up empty system data
|
||||
// if (message.SystemData is null) {
|
||||
// delete message.SystemData;
|
||||
// }
|
||||
|
||||
// Clean up empty template id
|
||||
// if (message.TemplateId is null)
|
||||
// delete message.templateId;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private void AddRewardItemsToMessage(Message message, MessageItems? itemsToSendToPlayer, long? maxStorageTimeSeconds)
|
||||
{
|
||||
if ((itemsToSendToPlayer?.Data?.Count ?? 0) > 0)
|
||||
{
|
||||
message.Items = itemsToSendToPlayer;
|
||||
message.HasRewards = true;
|
||||
message.MaxStorageTime = maxStorageTimeSeconds;
|
||||
message.RewardCollected = false;
|
||||
}
|
||||
}
|
||||
|
||||
private MessageItems ProcessItemsBeforeAddingToMail(MessageType? dialogType, SendMessageDetails messageDetails)
|
||||
{
|
||||
var items = _databaseService.GetItems();
|
||||
|
||||
MessageItems itemsToSendToPlayer = new();
|
||||
if ((messageDetails.Items?.Count ?? 0) > 0)
|
||||
{
|
||||
// Find base item that should be the 'primary' + have its parent id be used as the dialogs 'stash' value
|
||||
var parentItem = GetBaseItemFromRewards(messageDetails.Items);
|
||||
if (parentItem is null)
|
||||
{
|
||||
_localisationService.GetText("mailsend-missing_parent", new
|
||||
{
|
||||
TraderId = messageDetails.Trader,
|
||||
Sender = messageDetails.Sender,
|
||||
});
|
||||
|
||||
return itemsToSendToPlayer;
|
||||
}
|
||||
|
||||
// No parent id, generate random id and add (doesn't need to be actual parentId from db, only unique)
|
||||
if (parentItem?.ParentId is null)
|
||||
parentItem.ParentId = _hashUtil.Generate();
|
||||
|
||||
itemsToSendToPlayer = new()
|
||||
{
|
||||
Stash = parentItem.ParentId, Data = new()
|
||||
};
|
||||
|
||||
// Ensure Ids are unique and cont collide with items in player inventory later
|
||||
messageDetails.Items = _itemHelper.ReplaceIDs(messageDetails.Items);
|
||||
|
||||
foreach (var reward in messageDetails.Items)
|
||||
{
|
||||
// Ensure item exists in items db
|
||||
var itemTemplate = items[reward.Template];
|
||||
if (itemTemplate is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("dialog-missing_item_template", new
|
||||
{
|
||||
Tpl = reward.Template,
|
||||
Type = dialogType,
|
||||
}));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure every 'base/root' item has the same parentId + has a slotid of 'main'
|
||||
if (!(reward.SlotId is not null) || reward.SlotId == "hideout" || reward.ParentId == parentItem.ParentId)
|
||||
{
|
||||
// Reward items NEED a parent id + slotid
|
||||
reward.ParentId = parentItem.ParentId;
|
||||
reward.SlotId = "main";
|
||||
}
|
||||
|
||||
// Boxes can contain sub-items
|
||||
if (_itemHelper.IsOfBaseclass(itemTemplate.Id, BaseClasses.AMMO_BOX))
|
||||
{
|
||||
var boxAndCartridges = new List<Item>();
|
||||
boxAndCartridges.Add(reward);
|
||||
_itemHelper.AddCartridgesToAmmoBox(boxAndCartridges, itemTemplate);
|
||||
|
||||
// Push box + cartridge children into array
|
||||
itemsToSendToPlayer.Data.AddRange(boxAndCartridges);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (itemTemplate.Properties.StackSlots is not null)
|
||||
_logger.Error(_localisationService.GetText("mail-unable_to_give_gift_not_handled", itemTemplate.Id));
|
||||
|
||||
// Item is sanitised and ready to be pushed into holding array
|
||||
itemsToSendToPlayer.Data.Add(reward);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove empty data property if no rewards
|
||||
// if (itemsToSendToPlayer.Data.Count == 0)
|
||||
// delete itemsToSendToPlayer.data;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
private Item GetBaseItemFromRewards(List<Item>? items)
|
||||
{
|
||||
// Only one item in reward, return it
|
||||
if (items?.Count == 1)
|
||||
return items[0];
|
||||
|
||||
// Find first item with slotId that indicates its a 'base' item
|
||||
var item = items.FirstOrDefault(x => _slotNames.Contains(x.SlotId ?? ""));
|
||||
if (item is not null)
|
||||
return item;
|
||||
|
||||
// Not a singlular item + no items have a hideout/main slotid
|
||||
// Look for first item without parent id
|
||||
item = items.FirstOrDefault(x => x.ParentId is null);
|
||||
if (item is not null)
|
||||
return item;
|
||||
|
||||
// Just return first item in array
|
||||
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
|
||||
*/
|
||||
private Dialogue GetDialog(SendMessageDetails messageDetails)
|
||||
{
|
||||
var dialogsInProfile = _dialogueHelper.GetDialogsForProfile(messageDetails.RecipientId);
|
||||
var senderId = GetMessageSenderIdByType(messageDetails);
|
||||
if (senderId is null)
|
||||
throw new Exception(_localisationService.GetText("mail-unable_to_find_message_sender_by_id", messageDetails.Sender));
|
||||
|
||||
// Does dialog exist
|
||||
var senderDialog = dialogsInProfile[senderId];
|
||||
if (senderDialog is null)
|
||||
{
|
||||
// create if doesnt
|
||||
dialogsInProfile[senderId] = senderDialog = new Dialogue()
|
||||
{
|
||||
Id = senderId,
|
||||
Type = (messageDetails.DialogType is not null) ? messageDetails.DialogType : messageDetails.Sender,
|
||||
Messages = new(),
|
||||
Pinned = false,
|
||||
New = 0,
|
||||
AttachmentsNew = 0
|
||||
};
|
||||
|
||||
senderDialog = dialogsInProfile[senderId];
|
||||
}
|
||||
|
||||
return senderDialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate sender id by the sender enum type
|
||||
* @param messageDetails
|
||||
* @returns gets an id of the individual sending it
|
||||
*/
|
||||
private string? GetMessageSenderIdByType(SendMessageDetails messageDetails)
|
||||
{
|
||||
if (messageDetails.Sender == MessageType.SYSTEM_MESSAGE)
|
||||
return _systemSenderId;
|
||||
|
||||
if (messageDetails.Sender == MessageType.NPC_TRADER || messageDetails.DialogType == MessageType.NPC_TRADER)
|
||||
return (messageDetails.Trader is not null) ? _traderHelper.GetValidTraderIdByEnumValue(messageDetails.Trader) : null;
|
||||
|
||||
if (messageDetails.Sender == MessageType.USER_MESSAGE)
|
||||
return messageDetails.SenderDetails?.Id;
|
||||
|
||||
if (messageDetails.SenderDetails?.Id is not null)
|
||||
return messageDetails.SenderDetails.Id;
|
||||
|
||||
if (messageDetails.Trader is not null)
|
||||
return _traderHelper.GetValidTraderIdByEnumValue(messageDetails.Trader);
|
||||
|
||||
_logger.Warning($"Unable to handle message of type: {messageDetails.Sender}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user