partially implemented GiveSptCommand

This commit is contained in:
Chomp
2025-01-28 14:53:50 +00:00
parent 817a7b0694
commit e7e3cdf6d3
@@ -1,13 +1,42 @@
using SptCommon.Annotations;
using System.Text.RegularExpressions;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.Dialog;
using Core.Models.Eft.Profile;
using Core.Models.Enums;
using Core.Models.Utils;
using Core.Services;
using Core.Utils;
using Core.Utils.Cloners;
using SptCommon.Annotations;
namespace Core.Helpers.Dialog.Commando.SptCommands.GiveCommand;
namespace Core.Helpers.Dialogue.Commando.SptCommands.GiveCommand;
[Injectable]
public class GiveSptCommand
public class GiveSptCommand(
ISptLogger<GiveSptCommand> _logger,
HashUtil _hashUtil,
DatabaseService _databaseService,
ItemHelper _itemHelper,
PresetHelper _presetHelper,
ItemFilterService _itemFilterService,
MailSendService _mailSendService,
LocaleService _localeService,
ICloner _cloner
)
{
protected Dictionary<string, SavedCommand> _savedCommand = new();
//private const Regex _commandRegex = new Regex(@"/^spt give(((([a - z]{ 2,5}) )?")(.+)"|\w+) )?([0 - 9]+)$/";
private const double _acceptableConfidence = 0.9d;
// Exception for flares
protected readonly HashSet<string> _excludedPresetItems =
[
ItemTpl.FLARE_RSP30_REACTIVE_SIGNAL_CARTRIDGE_RED,
ItemTpl.FLARE_RSP30_REACTIVE_SIGNAL_CARTRIDGE_GREEN,
ItemTpl.FLARE_RSP30_REACTIVE_SIGNAL_CARTRIDGE_YELLOW
];
public string GetCommand()
{
return "give";
@@ -15,14 +44,198 @@ public class GiveSptCommand
public string GetCommandHelp()
{
return "spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: " +
"spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give [\"item name\"] [quantity]\n\t\tEx: spt give \"pack of sugar\" 10\n\n\tspt " +
"give [locale] [\"item name\"] [quantity]\n\t\tEx: spt give fr \"figurine de chat\" 3";
return
"spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: " +
"spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give [\"item name\"] [quantity]\n\t\tEx: spt give \"pack of sugar\" 10\n\n\tspt " +
"give [locale] [\"item name\"] [quantity]\n\t\tEx: spt give fr \"figurine de chat\" 3";
}
public string PerformAction(UserDialogInfo commandHandler, string sessionId, SendMessageRequest request)
{
throw new NotImplementedException();
/**
if (!_commandRegex.IsMatch(request.Text)) {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of give command. Use 'help' for more information.");
return request.DialogId;
}
var result = _commandRegex.Match(request.Text);
string item;
int quantity;
bool isItemName;
string? locale = null;
Dictionary<string, string>? localizedGlobal = null;
// This is a reply to a give request previously made pending a reply
if (result.Groups[1].Value == null) {
if (!_savedCommand.ContainsKey(sessionId)) {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid use of give command. Use 'help' for more information."
);
return request.DialogId;
}
_savedCommand.TryGetValue(sessionId, out var savedCommand);
var locationSixValue = +int.Parse( result.Groups[6].Value);
if (locationSixValue > savedCommand.PotentialItemNames.Count) {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid selection. Outside of bounds! Use 'help' for more information.");
return request.DialogId;
}
item = savedCommand.PotentialItemNames[locationSixValue - 1];
quantity = savedCommand.Quantity;
locale = savedCommand.Locale;
isItemName = true;
_savedCommand.Remove(sessionId);
} else {
// A new give request was entered, we need to ignore the old saved command
if (_savedCommand.ContainsKey(sessionId)) {
_savedCommand.Remove(sessionId);
}
isItemName = result.Groups[5].Value != null;
item = result.Groups[5].Value is not null ? result.Groups[5].Value : result.Groups[2].Value;
quantity = +int.Parse(result.Groups[6].Value);
if (quantity <= 0) {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"Invalid quantity! Must be 1 or higher. Use 'help' for more information.");
return request.DialogId;
}
if (isItemName) {
try {
locale = result.Groups[4] ?? _localeService.GetDesiredGameLocale() ?? "en";
} catch (Exception ex) {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
$"An error occurred while trying to use localized text. Locale will be defaulted to 'en'. {ex.Message}");
_logger.Warning(ex.Message);
locale = "en";
}
localizedGlobal = GetGlobalsLocale(locale);
var closestItemsMatchedByName = _itemHelper
.GetItems()
.Where((i) => IsItemAllowed(i))
.Select((i) => localizedGlobal[$"{i?.Id} Name"]?.ToLower() ?? i.Properties.Name)
.Where((i) => !string.IsNullOrEmpty(i))
.Select((i) => ({ Match = StringSimilarity(item.ToLower(), i.ToLower())ItemName = i }))
.Sort((a1, a2) => a2.match - a1.match);
if (closestItemsMatchedByName[0].match >= _acceptableConfidence) {
item = closestItemsMatchedByName[0].ItemName;
} else {
var i = 1;
var slicedItems = closestItemsMatchedByName.Slice(0, 10);
// max 10 item names and map them
var itemList = slicedItems
.map((match) => $"{i++}. {match.ItemName} (conf: ${(match.match * 100).toFixed(2)})")
.Join("\n");
_savedCommand.Add(
sessionId,
new SavedCommand(
quantity,
slicedItems.map((item) => item.ItemName),
locale));
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"Could not find exact match. Closest matches are:\n\n${itemList}\n\nUse 'spt give [number]' to select one.");
return request.DialogId;
}
}
}
localizedGlobal ??= GetGlobalsLocale(locale ?? "en");
// If item is an item name, we need to search using that item name and the locale which one we want otherwise
// item is just the tplId.
var tplId = isItemName
? _itemHelper
.GetItems()
.Where((i) => IsItemAllowed(i))
.FirstOrDefault((i) => (localizedGlobal[$"{i?.Id} Name"]?.ToLower() ?? i.Properties.Name) == item).Id
: item;
var checkedItem = _itemHelper.GetItem(tplId);
if (!checkedItem.Key) {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"That item could not be found. Please refine your request and try again.");
return request.DialogId;
}
List<Item> itemsToSend = [];
var preset = _presetHelper.GetDefaultPreset(checkedItem.Value.Id);
if (preset is not null && !_excludedPresetItems.Contains(checkedItem.Value.Id)) {
for (var i = 0; i < quantity; i++) {
var items = _cloner.Clone(preset.Items);
items = _itemHelper.ReplaceIDs(items);
itemsToSend.AddRange(items);
}
} else if (_itemHelper.IsOfBaseclass(checkedItem.Value.Id, BaseClasses.AMMO_BOX)) {
for (var i = 0; i < quantity; i++) {
List<Item> ammoBoxArray = [];
ammoBoxArray.Add( new Item{ Id = _hashUtil.Generate(), Template = checkedItem.Value.Id });
// DO NOT generate the ammo box cartridges, the mail service does it for us! :)
// _itemHelper.addCartridgesToAmmoBox(ammoBoxArray, checkedItem[1]);
itemsToSend.AddRange(ammoBoxArray);
}
} else {
if (checkedItem.Value.Properties.StackMaxSize == 1) {
for (var i = 0; i < quantity; i++) {
itemsToSend.Add( new Item{
Id = _hashUtil.Generate(),
Template = checkedItem.Value.Id,
Upd = _itemHelper.generateUpdForItem(checkedItem.Value) });
}
} else {
var itemToSend = new Item{
Id = _hashUtil.Generate(),
Template = checkedItem.Value.Id,
Upd = _itemHelper.generateUpdForItem(checkedItem.Value),
};
itemToSend.Upd.StackObjectsCount = quantity;
try {
itemsToSend.AddRange(_itemHelper.SplitStack(itemToSend));
} catch {
_mailSendService.SendUserMessageToPlayer(
sessionId,
commandHandler,
"Too many items requested. Please lower the amount and try again.");
return request.DialogId;
}
}
}
// Flag the items as FiR
_itemHelper.SetFoundInRaid(itemsToSend);
_mailSendService.SendSystemMessageToPlayer(sessionId, "SPT GIVE", itemsToSend);
return request.DialogId;
*/
}
protected Dictionary<string, string> GetGlobalsLocale(string desiredLocale)
{
return _databaseService.GetLocales().Global.TryGetValue(desiredLocale, out var locale)
? locale.Value
: _databaseService.GetLocales().Global["en"].Value;
}
/**
@@ -32,6 +245,16 @@ public class GiveSptCommand
*/
protected bool IsItemAllowed(TemplateItem templateItem)
{
throw new NotImplementedException();
return templateItem.Type != "Node" &&
!_itemHelper.IsQuestItem(templateItem.Id) &&
!_itemFilterService.IsItemBlacklisted(templateItem.Id) &&
(templateItem.Properties?.Prefab?.Path ?? "") != "" &&
!_itemHelper.IsOfBaseclasses(
templateItem.Id,
[
BaseClasses.HIDEOUT_AREA_CONTAINER, BaseClasses.LOOT_CONTAINER,
BaseClasses.RANDOM_LOOT_CONTAINER, BaseClasses.MOB_CONTAINER
]
);
}
}