Updated class param formatting
This commit is contained in:
@@ -8,8 +8,8 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Helpers.Dialogue;
|
namespace SPTarkov.Server.Core.Helpers.Dialogue;
|
||||||
|
|
||||||
public abstract class AbstractDialogChatBot(
|
public abstract class AbstractDialogChatBot(
|
||||||
ISptLogger<AbstractDialogChatBot> _logger,
|
ISptLogger<AbstractDialogChatBot> logger,
|
||||||
MailSendService _mailSendService,
|
MailSendService mailSendService,
|
||||||
ServerLocalisationService localisationService,
|
ServerLocalisationService localisationService,
|
||||||
IEnumerable<IChatCommand> chatCommands
|
IEnumerable<IChatCommand> chatCommands
|
||||||
) : IDialogueChatBot
|
) : IDialogueChatBot
|
||||||
@@ -22,7 +22,7 @@ public abstract class AbstractDialogChatBot(
|
|||||||
{
|
{
|
||||||
if (request.Text.Length == 0)
|
if (request.Text.Length == 0)
|
||||||
{
|
{
|
||||||
_logger.Error(localisationService.GetText("chatbot-command_was_empty"));
|
logger.Error(localisationService.GetText("chatbot-command_was_empty"));
|
||||||
|
|
||||||
return request.DialogId;
|
return request.DialogId;
|
||||||
}
|
}
|
||||||
@@ -43,20 +43,20 @@ public abstract class AbstractDialogChatBot(
|
|||||||
return await SendPlayerHelpMessage(sessionId, request);
|
return await SendPlayerHelpMessage(sessionId, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
_mailSendService.SendUserMessageToPlayer(sessionId, GetChatBot(), GetUnrecognizedCommandMessage(), [], null);
|
mailSendService.SendUserMessageToPlayer(sessionId, GetChatBot(), GetUnrecognizedCommandMessage(), [], null);
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async ValueTask<string> SendPlayerHelpMessage(MongoId sessionId, SendMessageRequest request)
|
protected async ValueTask<string> SendPlayerHelpMessage(MongoId sessionId, SendMessageRequest request)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(sessionId, GetChatBot(), "The available commands will be listed below:", [], null);
|
mailSendService.SendUserMessageToPlayer(sessionId, GetChatBot(), "The available commands will be listed below:", [], null);
|
||||||
foreach (var chatCommand in _chatCommands.Values)
|
foreach (var chatCommand in _chatCommands.Values)
|
||||||
{
|
{
|
||||||
// due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order
|
// due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
GetChatBot(),
|
GetChatBot(),
|
||||||
$"Commands available for \"{chatCommand.CommandPrefix}\" prefix:",
|
$"Commands available for \"{chatCommand.CommandPrefix}\" prefix:",
|
||||||
@@ -68,7 +68,7 @@ public abstract class AbstractDialogChatBot(
|
|||||||
|
|
||||||
foreach (var subCommand in chatCommand.Commands)
|
foreach (var subCommand in chatCommand.Commands)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
GetChatBot(),
|
GetChatBot(),
|
||||||
$"Subcommand {subCommand}:\n{chatCommand.GetCommandHelp(subCommand)}",
|
$"Subcommand {subCommand}:\n{chatCommand.GetCommandHelp(subCommand)}",
|
||||||
|
|||||||
+29
-29
@@ -15,14 +15,14 @@ namespace SPTarkov.Server.Core.Helpers.Dialogue.Commando.SptCommands.GiveCommand
|
|||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class GiveSptCommand(
|
public class GiveSptCommand(
|
||||||
ISptLogger<GiveSptCommand> _logger,
|
ISptLogger<GiveSptCommand> logger,
|
||||||
ItemHelper _itemHelper,
|
ItemHelper itemHelper,
|
||||||
DatabaseService databaseService,
|
DatabaseService databaseService,
|
||||||
PresetHelper _presetHelper,
|
PresetHelper presetHelper,
|
||||||
ItemFilterService _itemFilterService,
|
ItemFilterService itemFilterService,
|
||||||
MailSendService _mailSendService,
|
MailSendService mailSendService,
|
||||||
LocaleService _localeService,
|
LocaleService localeService,
|
||||||
ICloner _cloner
|
ICloner cloner
|
||||||
) : ISptCommand
|
) : ISptCommand
|
||||||
{
|
{
|
||||||
private const double _acceptableConfidence = 0.9d;
|
private const double _acceptableConfidence = 0.9d;
|
||||||
@@ -57,7 +57,7 @@ public class GiveSptCommand(
|
|||||||
{
|
{
|
||||||
if (!_commandRegex.IsMatch(request.Text))
|
if (!_commandRegex.IsMatch(request.Text))
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of give command. Use 'help' for more information."
|
"Invalid use of give command. Use 'help' for more information."
|
||||||
@@ -78,7 +78,7 @@ public class GiveSptCommand(
|
|||||||
{
|
{
|
||||||
if (!_savedCommand.ContainsKey(sessionId))
|
if (!_savedCommand.ContainsKey(sessionId))
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of give command. Use 'help' for more information."
|
"Invalid use of give command. Use 'help' for more information."
|
||||||
@@ -90,7 +90,7 @@ public class GiveSptCommand(
|
|||||||
var locationSixValue = +int.Parse(result.Groups[6].Value);
|
var locationSixValue = +int.Parse(result.Groups[6].Value);
|
||||||
if (locationSixValue > savedCommand.PotentialItemNames.Count)
|
if (locationSixValue > savedCommand.PotentialItemNames.Count)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid selection. Outside of bounds! Use 'help' for more information."
|
"Invalid selection. Outside of bounds! Use 'help' for more information."
|
||||||
@@ -114,7 +114,7 @@ public class GiveSptCommand(
|
|||||||
quantity = +int.Parse(result.Groups[6].Value);
|
quantity = +int.Parse(result.Groups[6].Value);
|
||||||
if (quantity <= 0)
|
if (quantity <= 0)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid quantity! Must be 1 or higher. Use 'help' for more information."
|
"Invalid quantity! Must be 1 or higher. Use 'help' for more information."
|
||||||
@@ -126,17 +126,17 @@ public class GiveSptCommand(
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
locale = result.Groups[4].Value ?? _localeService.GetDesiredGameLocale() ?? "en";
|
locale = result.Groups[4].Value ?? localeService.GetDesiredGameLocale() ?? "en";
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
$"An error occurred while trying to use localized text. Locale will be defaulted to 'en'. {ex.Message}"
|
$"An error occurred while trying to use localized text. Locale will be defaulted to 'en'. {ex.Message}"
|
||||||
);
|
);
|
||||||
|
|
||||||
_logger.Warning(ex.Message);
|
logger.Warning(ex.Message);
|
||||||
locale = "en";
|
locale = "en";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ public class GiveSptCommand(
|
|||||||
// max 10 item names and map them
|
// max 10 item names and map them
|
||||||
var itemList = slicedItems.Select(match => $"{i++}. {match.ItemName} (conf: {Math.Round(match.Match * 100d), 2})");
|
var itemList = slicedItems.Select(match => $"{i++}. {match.ItemName} (conf: {Math.Round(match.Match * 100d), 2})");
|
||||||
_savedCommand.Add(sessionId, new SavedCommand(quantity, slicedItems.Select(item => item.ItemName).ToList(), locale));
|
_savedCommand.Add(sessionId, new SavedCommand(quantity, slicedItems.Select(item => item.ItemName).ToList(), locale));
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
$"Could not find exact match. Closest are:\n{string.Join("\n", itemList)}\n\nUse 'spt give [above number]' to select one."
|
$"Could not find exact match. Closest are:\n{string.Join("\n", itemList)}\n\nUse 'spt give [above number]' to select one."
|
||||||
@@ -186,10 +186,10 @@ public class GiveSptCommand(
|
|||||||
.Id
|
.Id
|
||||||
: item;
|
: item;
|
||||||
|
|
||||||
var checkedItem = _itemHelper.GetItem(tplId);
|
var checkedItem = itemHelper.GetItem(tplId);
|
||||||
if (!checkedItem.Key)
|
if (!checkedItem.Key)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"That item could not be found. Please refine your request and try again."
|
"That item could not be found. Please refine your request and try again."
|
||||||
@@ -198,17 +198,17 @@ public class GiveSptCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Item> itemsToSend = [];
|
List<Item> itemsToSend = [];
|
||||||
var preset = _presetHelper.GetDefaultPreset(checkedItem.Value.Id);
|
var preset = presetHelper.GetDefaultPreset(checkedItem.Value.Id);
|
||||||
if (preset is not null && !_excludedPresetItems.Contains(checkedItem.Value.Id))
|
if (preset is not null && !_excludedPresetItems.Contains(checkedItem.Value.Id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < quantity; i++)
|
for (var i = 0; i < quantity; i++)
|
||||||
{
|
{
|
||||||
var items = _cloner.Clone(preset.Items);
|
var items = cloner.Clone(preset.Items);
|
||||||
items = items.ReplaceIDs().ToList();
|
items = items.ReplaceIDs().ToList();
|
||||||
itemsToSend.AddRange(items);
|
itemsToSend.AddRange(items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_itemHelper.IsOfBaseclass(checkedItem.Value.Id, BaseClasses.AMMO_BOX))
|
else if (itemHelper.IsOfBaseclass(checkedItem.Value.Id, BaseClasses.AMMO_BOX))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < quantity; i++)
|
for (var i = 0; i < quantity; i++)
|
||||||
{
|
{
|
||||||
@@ -234,7 +234,7 @@ public class GiveSptCommand(
|
|||||||
{
|
{
|
||||||
Id = new MongoId(),
|
Id = new MongoId(),
|
||||||
Template = checkedItem.Value.Id,
|
Template = checkedItem.Value.Id,
|
||||||
Upd = _itemHelper.GenerateUpdForItem(checkedItem.Value),
|
Upd = itemHelper.GenerateUpdForItem(checkedItem.Value),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -245,16 +245,16 @@ public class GiveSptCommand(
|
|||||||
{
|
{
|
||||||
Id = new MongoId(),
|
Id = new MongoId(),
|
||||||
Template = checkedItem.Value.Id,
|
Template = checkedItem.Value.Id,
|
||||||
Upd = _itemHelper.GenerateUpdForItem(checkedItem.Value),
|
Upd = itemHelper.GenerateUpdForItem(checkedItem.Value),
|
||||||
};
|
};
|
||||||
itemToSend.Upd.StackObjectsCount = quantity;
|
itemToSend.Upd.StackObjectsCount = quantity;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
itemsToSend.AddRange(_itemHelper.SplitStack(itemToSend));
|
itemsToSend.AddRange(itemHelper.SplitStack(itemToSend));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Too many items requested. Please lower the amount and try again."
|
"Too many items requested. Please lower the amount and try again."
|
||||||
@@ -266,9 +266,9 @@ public class GiveSptCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Flag the items as FiR
|
// Flag the items as FiR
|
||||||
_itemHelper.SetFoundInRaid(itemsToSend);
|
itemHelper.SetFoundInRaid(itemsToSend);
|
||||||
|
|
||||||
_mailSendService.SendSystemMessageToPlayer(sessionId, $"SPT GIVE DELIVERY: {item}", itemsToSend);
|
mailSendService.SendSystemMessageToPlayer(sessionId, $"SPT GIVE DELIVERY: {item}", itemsToSend);
|
||||||
|
|
||||||
return new ValueTask<string>(request.DialogId);
|
return new ValueTask<string>(request.DialogId);
|
||||||
}
|
}
|
||||||
@@ -280,7 +280,7 @@ public class GiveSptCommand(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected Dictionary<string, string> GetGlobalsLocale(string desiredLocale)
|
protected Dictionary<string, string> GetGlobalsLocale(string desiredLocale)
|
||||||
{
|
{
|
||||||
return _localeService.GetLocaleDb(desiredLocale);
|
return localeService.GetLocaleDb(desiredLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -292,9 +292,9 @@ public class GiveSptCommand(
|
|||||||
{
|
{
|
||||||
return templateItem.Type != "Node"
|
return templateItem.Type != "Node"
|
||||||
&& !templateItem.IsQuestItem()
|
&& !templateItem.IsQuestItem()
|
||||||
&& !_itemFilterService.IsItemBlacklisted(templateItem.Id)
|
&& !itemFilterService.IsItemBlacklisted(templateItem.Id)
|
||||||
&& (templateItem.Properties?.Prefab?.Path ?? "") != ""
|
&& (templateItem.Properties?.Prefab?.Path ?? "") != ""
|
||||||
&& !_itemHelper.IsOfBaseclasses(
|
&& !itemHelper.IsOfBaseclasses(
|
||||||
templateItem.Id,
|
templateItem.Id,
|
||||||
[
|
[
|
||||||
BaseClasses.HIDEOUT_AREA_CONTAINER,
|
BaseClasses.HIDEOUT_AREA_CONTAINER,
|
||||||
|
|||||||
+9
-9
@@ -13,7 +13,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Helpers.Dialogue.Commando.SptCommands.ProfileCommand;
|
namespace SPTarkov.Server.Core.Helpers.Dialogue.Commando.SptCommands.ProfileCommand;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendService _mailSendService, ProfileHelper _profileHelper)
|
public class ProfileSptCommand(ISptLogger<ProfileSptCommand> logger, MailSendService mailSendService, ProfileHelper profileHelper)
|
||||||
: ISptCommand
|
: ISptCommand
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -49,7 +49,7 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
|
|
||||||
if (!isCommand && !isExamine)
|
if (!isCommand && !isExamine)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of trader command. Use 'help' for more information."
|
"Invalid use of trader command. Use 'help' for more information."
|
||||||
@@ -67,9 +67,9 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case "level":
|
case "level":
|
||||||
if (quantity < 1 || quantity > _profileHelper.GetMaxLevel())
|
if (quantity < 1 || quantity > profileHelper.GetMaxLevel())
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of profile command, the level was outside bounds: 1 to 70. Use 'help' for more information."
|
"Invalid use of profile command, the level was outside bounds: 1 to 70. Use 'help' for more information."
|
||||||
@@ -87,7 +87,7 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
|
|
||||||
if (enumSkill == null)
|
if (enumSkill == null)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of profile command, the skill was not found. Use 'help' for more information."
|
"Invalid use of profile command, the skill was not found. Use 'help' for more information."
|
||||||
@@ -97,7 +97,7 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
|
|
||||||
if (quantity is < 0 or > 51)
|
if (quantity is < 0 or > 51)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use 'help' for more information."
|
"Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use 'help' for more information."
|
||||||
@@ -114,7 +114,7 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
$"If you are reading this, this is bad. Please report this to SPT staff with a screenshot. Command: {command}."
|
$"If you are reading this, this is bad. Please report this to SPT staff with a screenshot. Command: {command}."
|
||||||
@@ -122,7 +122,7 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
return new ValueTask<string>(request.DialogId);
|
return new ValueTask<string>(request.DialogId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_mailSendService.SendSystemMessageToPlayer(
|
mailSendService.SendSystemMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
"A single ruble is being attached, required by BSG logic.",
|
"A single ruble is being attached, required by BSG logic.",
|
||||||
[
|
[
|
||||||
@@ -156,7 +156,7 @@ public class ProfileSptCommand(ISptLogger<ProfileSptCommand> _logger, MailSendSe
|
|||||||
|
|
||||||
protected ProfileChangeEvent HandleLevelCommand(int level)
|
protected ProfileChangeEvent HandleLevelCommand(int level)
|
||||||
{
|
{
|
||||||
var exp = _profileHelper.GetExperience(level);
|
var exp = profileHelper.GetExperience(level);
|
||||||
var profileChangeEvent = new ProfileChangeEvent
|
var profileChangeEvent = new ProfileChangeEvent
|
||||||
{
|
{
|
||||||
Id = new MongoId(),
|
Id = new MongoId(),
|
||||||
|
|||||||
+6
-7
@@ -14,8 +14,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Helpers.Dialogue.Commando.SptCommands.TraderCommand;
|
namespace SPTarkov.Server.Core.Helpers.Dialogue.Commando.SptCommands.TraderCommand;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class TraderSptCommand(ISptLogger<TraderSptCommand> _logger, TraderHelper _traderHelper, MailSendService _mailSendService)
|
public class TraderSptCommand(ISptLogger<TraderSptCommand> logger, TraderHelper traderHelper, MailSendService mailSendService) : ISptCommand
|
||||||
: ISptCommand
|
|
||||||
{
|
{
|
||||||
protected readonly Regex _commandRegex = new(@"^spt trader (?<trader>[\w]+) (?<command>rep|spend) (?<quantity>(?!0+)[0-9]+)$");
|
protected readonly Regex _commandRegex = new(@"^spt trader (?<trader>[\w]+) (?<command>rep|spend) (?<quantity>(?!0+)[0-9]+)$");
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ public class TraderSptCommand(ISptLogger<TraderSptCommand> _logger, TraderHelper
|
|||||||
{
|
{
|
||||||
if (!_commandRegex.IsMatch(request.Text))
|
if (!_commandRegex.IsMatch(request.Text))
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of trader command. Use 'help' for more information."
|
"Invalid use of trader command. Use 'help' for more information."
|
||||||
@@ -50,10 +49,10 @@ public class TraderSptCommand(ISptLogger<TraderSptCommand> _logger, TraderHelper
|
|||||||
var command = result.Groups["command"].Captures.Count > 0 ? result.Groups["command"].Captures[0].Value : null;
|
var command = result.Groups["command"].Captures.Count > 0 ? result.Groups["command"].Captures[0].Value : null;
|
||||||
var quantity = double.Parse(result.Groups["command"].Captures.Count > 0 ? result.Groups["quantity"].Captures[0].Value : "0");
|
var quantity = double.Parse(result.Groups["command"].Captures.Count > 0 ? result.Groups["quantity"].Captures[0].Value : "0");
|
||||||
|
|
||||||
var dbTrader = _traderHelper.GetTraderByNickName(trader);
|
var dbTrader = traderHelper.GetTraderByNickName(trader);
|
||||||
if (dbTrader == null)
|
if (dbTrader == null)
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of trader command, the trader was not found. Use 'help' for more information."
|
"Invalid use of trader command, the trader was not found. Use 'help' for more information."
|
||||||
@@ -74,7 +73,7 @@ public class TraderSptCommand(ISptLogger<TraderSptCommand> _logger, TraderHelper
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
_mailSendService.SendUserMessageToPlayer(
|
mailSendService.SendUserMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
commandHandler,
|
commandHandler,
|
||||||
"Invalid use of trader command, ProfileChangeEventType was not found. Use 'help' for more information."
|
"Invalid use of trader command, ProfileChangeEventType was not found. Use 'help' for more information."
|
||||||
@@ -84,7 +83,7 @@ public class TraderSptCommand(ISptLogger<TraderSptCommand> _logger, TraderHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_mailSendService.SendSystemMessageToPlayer(
|
mailSendService.SendSystemMessageToPlayer(
|
||||||
sessionId,
|
sessionId,
|
||||||
"A single ruble is being attached, required by BSG logic.",
|
"A single ruble is being attached, required by BSG logic.",
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -6,19 +6,19 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Loaders;
|
namespace SPTarkov.Server.Core.Loaders;
|
||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class OnWebAppBuildModLoader(ISptLogger<OnWebAppBuildModLoader> _logger, IEnumerable<IOnWebAppBuildModAsync> _onWebAppBuildMods)
|
public class OnWebAppBuildModLoader(ISptLogger<OnWebAppBuildModLoader> logger, IEnumerable<IOnWebAppBuildModAsync> onWebAppBuildMods)
|
||||||
{
|
{
|
||||||
public async Task OnLoad()
|
public async Task OnLoad()
|
||||||
{
|
{
|
||||||
if (ProgramStatics.MODS())
|
if (ProgramStatics.MODS())
|
||||||
{
|
{
|
||||||
_logger.Info("Loading OnWebAppBuildMods...");
|
logger.Info("Loading OnWebAppBuildMods...");
|
||||||
foreach (var onWebAppBuildMod in _onWebAppBuildMods)
|
foreach (var onWebAppBuildMod in onWebAppBuildMods)
|
||||||
{
|
{
|
||||||
await onWebAppBuildMod.OnWebAppBuildAsync();
|
await onWebAppBuildMod.OnWebAppBuildAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Finished loading OnWebAppBuildMods...");
|
logger.Info("Finished loading OnWebAppBuildMods...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ namespace SPTarkov.Server.Core.Loaders;
|
|||||||
|
|
||||||
[Obsolete("This mod loader is obsolete and will be removed in 4.1.0. See documentation in IPostDBLoadModAsync for more information.")]
|
[Obsolete("This mod loader is obsolete and will be removed in 4.1.0. See documentation in IPostDBLoadModAsync for more information.")]
|
||||||
[Injectable(TypePriority = OnLoadOrder.PostDBModLoader)]
|
[Injectable(TypePriority = OnLoadOrder.PostDBModLoader)]
|
||||||
public class PostDBModLoader(ISptLogger<PostDBModLoader> _logger, IEnumerable<IPostDBLoadModAsync> _postDbLoadMods) : IOnLoad
|
public class PostDBModLoader(ISptLogger<PostDBModLoader> logger, IEnumerable<IPostDBLoadModAsync> postDbLoadMods) : IOnLoad
|
||||||
{
|
{
|
||||||
public async Task OnLoad()
|
public async Task OnLoad()
|
||||||
{
|
{
|
||||||
if (ProgramStatics.MODS())
|
if (ProgramStatics.MODS())
|
||||||
{
|
{
|
||||||
_logger.Info("Loading PostDBMods...");
|
logger.Info("Loading PostDBMods...");
|
||||||
foreach (var postDbLoadMod in _postDbLoadMods)
|
foreach (var postDbLoadMod in postDbLoadMods)
|
||||||
{
|
{
|
||||||
await postDbLoadMod.PostDBLoadAsync();
|
await postDbLoadMod.PostDBLoadAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Finished loading PostDBMods...");
|
logger.Info("Finished loading PostDBMods...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ namespace SPTarkov.Server.Core.Loaders;
|
|||||||
|
|
||||||
[Obsolete("This mod loader is obsolete and will be removed in 4.1.0. See documentation in IPostSptLoadModAsync for more information.")]
|
[Obsolete("This mod loader is obsolete and will be removed in 4.1.0. See documentation in IPostSptLoadModAsync for more information.")]
|
||||||
[Injectable(TypePriority = OnLoadOrder.PostSptModLoader)]
|
[Injectable(TypePriority = OnLoadOrder.PostSptModLoader)]
|
||||||
public class PostSptModLoader(ISptLogger<PostSptModLoader> _logger, IEnumerable<IPostSptLoadModAsync> _postSptLoadMods) : IOnLoad
|
public class PostSptModLoader(ISptLogger<PostSptModLoader> logger, IEnumerable<IPostSptLoadModAsync> postSptLoadMods) : IOnLoad
|
||||||
{
|
{
|
||||||
public async Task OnLoad()
|
public async Task OnLoad()
|
||||||
{
|
{
|
||||||
if (ProgramStatics.MODS())
|
if (ProgramStatics.MODS())
|
||||||
{
|
{
|
||||||
_logger.Info("Loading PostSptMods...");
|
logger.Info("Loading PostSptMods...");
|
||||||
foreach (var postSptLoadMod in _postSptLoadMods)
|
foreach (var postSptLoadMod in postSptLoadMods)
|
||||||
{
|
{
|
||||||
await postSptLoadMod.PostSptLoadAsync();
|
await postSptLoadMod.PostSptLoadAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Finished loading PostSptMods...");
|
logger.Info("Finished loading PostSptMods...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,19 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Loaders;
|
namespace SPTarkov.Server.Core.Loaders;
|
||||||
|
|
||||||
[Injectable(InjectionType.Singleton, TypePriority = OnLoadOrder.PreSptModLoader)]
|
[Injectable(InjectionType.Singleton, TypePriority = OnLoadOrder.PreSptModLoader)]
|
||||||
public class PreSptModLoader(ISptLogger<PreSptModLoader> _logger, IEnumerable<IPreSptLoadModAsync> _preSptLoadMods) : IOnLoad
|
public class PreSptModLoader(ISptLogger<PreSptModLoader> logger, IEnumerable<IPreSptLoadModAsync> preSptLoadMods) : IOnLoad
|
||||||
{
|
{
|
||||||
public async Task OnLoad()
|
public async Task OnLoad()
|
||||||
{
|
{
|
||||||
if (ProgramStatics.MODS())
|
if (ProgramStatics.MODS())
|
||||||
{
|
{
|
||||||
_logger.Info("Loading PreSptMods...");
|
logger.Info("Loading PreSptMods...");
|
||||||
foreach (var postSptLoadMod in _preSptLoadMods)
|
foreach (var postSptLoadMod in preSptLoadMods)
|
||||||
{
|
{
|
||||||
await postSptLoadMod.PreSptLoadAsync();
|
await postSptLoadMod.PreSptLoadAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Info("Finished loading PreSptMods...");
|
logger.Info("Finished loading PreSptMods...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ namespace SPTarkov.Server.Core.Servers;
|
|||||||
public class ConfigServer
|
public class ConfigServer
|
||||||
{
|
{
|
||||||
protected readonly FrozenSet<string> acceptableFileExtensions = ["json", "jsonc"];
|
protected readonly FrozenSet<string> acceptableFileExtensions = ["json", "jsonc"];
|
||||||
protected readonly FileUtil _fileUtil;
|
protected readonly FileUtil FileUtil;
|
||||||
protected readonly JsonUtil _jsonUtil;
|
protected readonly JsonUtil JsonUtil;
|
||||||
protected readonly ISptLogger<ConfigServer> _logger;
|
protected readonly ISptLogger<ConfigServer> Logger;
|
||||||
private static readonly Dictionary<string, object> _configs = new();
|
private static readonly Dictionary<string, object> _configs = new();
|
||||||
|
|
||||||
public ConfigServer(ISptLogger<ConfigServer> logger, JsonUtil jsonUtil, FileUtil fileUtil)
|
public ConfigServer(ISptLogger<ConfigServer> logger, JsonUtil jsonUtil, FileUtil fileUtil)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
Logger = logger;
|
||||||
_jsonUtil = jsonUtil;
|
JsonUtil = jsonUtil;
|
||||||
_fileUtil = fileUtil;
|
FileUtil = fileUtil;
|
||||||
|
|
||||||
if (_configs.Count == 0)
|
if (_configs.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -60,37 +60,37 @@ public class ConfigServer
|
|||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (Logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug("Importing configs...");
|
Logger.Debug("Importing configs...");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all filepaths
|
// Get all filepaths
|
||||||
const string filepath = "./SPT_Data/configs/";
|
const string filepath = "./SPT_Data/configs/";
|
||||||
var files = _fileUtil.GetFiles(filepath);
|
var files = FileUtil.GetFiles(filepath);
|
||||||
|
|
||||||
// Add file content to result
|
// Add file content to result
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
if (acceptableFileExtensions.Contains(_fileUtil.GetFileExtension(file)))
|
if (acceptableFileExtensions.Contains(FileUtil.GetFileExtension(file)))
|
||||||
{
|
{
|
||||||
var type = GetConfigTypeByFilename(file);
|
var type = GetConfigTypeByFilename(file);
|
||||||
var deserializedContent = _jsonUtil.DeserializeFromFile(file, type);
|
var deserializedContent = JsonUtil.DeserializeFromFile(file, type);
|
||||||
|
|
||||||
if (deserializedContent == null)
|
if (deserializedContent == null)
|
||||||
{
|
{
|
||||||
_logger.Error($"Config file: {file} is corrupt. Use a site like: https://jsonlint.com to find the issue.");
|
Logger.Error($"Config file: {file} is corrupt. Use a site like: https://jsonlint.com to find the issue.");
|
||||||
throw new Exception($"Server will not run until the: {file} config error mentioned above is fixed");
|
throw new Exception($"Server will not run until the: {file} config error mentioned above is fixed");
|
||||||
}
|
}
|
||||||
|
|
||||||
_configs[$"spt-{_fileUtil.StripExtension(file)}"] = deserializedContent;
|
_configs[$"spt-{FileUtil.StripExtension(file)}"] = deserializedContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type GetConfigTypeByFilename(string filename)
|
private Type GetConfigTypeByFilename(string filename)
|
||||||
{
|
{
|
||||||
var type = Enum.GetValues<ConfigTypes>().First(en => en.GetValue().Contains(_fileUtil.StripExtension(filename)));
|
var type = Enum.GetValues<ConfigTypes>().First(en => en.GetValue().Contains(FileUtil.StripExtension(filename)));
|
||||||
return type.GetConfigType();
|
return type.GetConfigType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ namespace SPTarkov.Server.Core.Servers.Http;
|
|||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class SptHttpListener(
|
public class SptHttpListener(
|
||||||
HttpRouter _httpRouter,
|
HttpRouter httpRouter,
|
||||||
IEnumerable<ISerializer> _serializers,
|
IEnumerable<ISerializer> serializers,
|
||||||
ISptLogger<SptHttpListener> _logger,
|
ISptLogger<SptHttpListener> logger,
|
||||||
ISptLogger<RequestLogger> _requestsLogger,
|
ISptLogger<RequestLogger> requestsLogger,
|
||||||
JsonUtil _jsonUtil,
|
JsonUtil jsonUtil,
|
||||||
HttpResponseUtil _httpResponseUtil,
|
HttpResponseUtil httpResponseUtil,
|
||||||
ServerLocalisationService _serverLocalisationService
|
ServerLocalisationService serverLocalisationService
|
||||||
) : IHttpListener
|
) : IHttpListener
|
||||||
{
|
{
|
||||||
// We want to read 1KB at a time, for most request this is already big enough
|
// We want to read 1KB at a time, for most request this is already big enough
|
||||||
@@ -30,8 +30,8 @@ public class SptHttpListener(
|
|||||||
|
|
||||||
private static readonly ImmutableHashSet<string> SupportedMethods = ["GET", "PUT", "POST"];
|
private static readonly ImmutableHashSet<string> SupportedMethods = ["GET", "PUT", "POST"];
|
||||||
|
|
||||||
protected readonly HttpRouter _router = _httpRouter;
|
protected readonly HttpRouter _router = httpRouter;
|
||||||
protected readonly IEnumerable<ISerializer> _serializers = _serializers;
|
protected readonly IEnumerable<ISerializer> _serializers = serializers;
|
||||||
|
|
||||||
public bool CanHandle(MongoId _, HttpRequest req)
|
public bool CanHandle(MongoId _, HttpRequest req)
|
||||||
{
|
{
|
||||||
@@ -92,9 +92,9 @@ public class SptHttpListener(
|
|||||||
|
|
||||||
if (!requestIsCompressed)
|
if (!requestIsCompressed)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(body);
|
logger.Debug(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ public class SptHttpListener(
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
_logger.Warning($"{_serverLocalisationService.GetText("unknown_request")}: {req.Method}");
|
logger.Warning($"{serverLocalisationService.GetText("unknown_request")}: {req.Method}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,15 +123,15 @@ public class SptHttpListener(
|
|||||||
{
|
{
|
||||||
body ??= new object();
|
body ??= new object();
|
||||||
|
|
||||||
var bodyInfo = _jsonUtil.Serialize(body);
|
var bodyInfo = jsonUtil.Serialize(body);
|
||||||
|
|
||||||
if (IsDebugRequest(req))
|
if (IsDebugRequest(req))
|
||||||
{
|
{
|
||||||
// Send only raw response without transformation
|
// Send only raw response without transformation
|
||||||
await SendJson(resp, output, sessionID);
|
await SendJson(resp, output, sessionID);
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Response: {output}");
|
logger.Debug($"Response: {output}");
|
||||||
}
|
}
|
||||||
|
|
||||||
LogRequest(req, output);
|
LogRequest(req, output);
|
||||||
@@ -173,7 +173,7 @@ public class SptHttpListener(
|
|||||||
if (ProgramStatics.ENTRY_TYPE() != EntryType.RELEASE)
|
if (ProgramStatics.ENTRY_TYPE() != EntryType.RELEASE)
|
||||||
{
|
{
|
||||||
var log = new Response(req.Method, output);
|
var log = new Response(req.Method, output);
|
||||||
_requestsLogger.Info($"RESPONSE={_jsonUtil.Serialize(log)}");
|
requestsLogger.Info($"RESPONSE={jsonUtil.Serialize(log)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,15 +184,15 @@ public class SptHttpListener(
|
|||||||
// Route doesn't exist or response is not properly set up
|
// Route doesn't exist or response is not properly set up
|
||||||
if (string.IsNullOrEmpty(output))
|
if (string.IsNullOrEmpty(output))
|
||||||
{
|
{
|
||||||
_logger.Error(_serverLocalisationService.GetText("unhandled_response", req.Path.ToString()));
|
logger.Error(serverLocalisationService.GetText("unhandled_response", req.Path.ToString()));
|
||||||
output = _httpResponseUtil.GetBody<object?>(null, BackendErrorCodes.HTTPNotFound, $"UNHANDLED RESPONSE: {req.Path.ToString()}");
|
output = httpResponseUtil.GetBody<object?>(null, BackendErrorCodes.HTTPNotFound, $"UNHANDLED RESPONSE: {req.Path.ToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProgramStatics.ENTRY_TYPE() != EntryType.RELEASE)
|
if (ProgramStatics.ENTRY_TYPE() != EntryType.RELEASE)
|
||||||
{
|
{
|
||||||
// Parse quest info into object
|
// Parse quest info into object
|
||||||
var log = new Request(req.Method, new RequestData(req.Path.ToString(), req.Headers));
|
var log = new Request(req.Method, new RequestData(req.Path.ToString(), req.Headers));
|
||||||
_requestsLogger.Info($"REQUEST={_jsonUtil.Serialize(log)}");
|
requestsLogger.Info($"REQUEST={jsonUtil.Serialize(log)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ namespace SPTarkov.Server.Core.Servers;
|
|||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class HttpServer(
|
public class HttpServer(
|
||||||
ISptLogger<HttpServer> _logger,
|
ISptLogger<HttpServer> logger,
|
||||||
ServerLocalisationService _serverLocalisationService,
|
ServerLocalisationService serverLocalisationService,
|
||||||
ConfigServer _configServer,
|
ConfigServer configServer,
|
||||||
WebSocketServer _webSocketServer,
|
WebSocketServer webSocketServer,
|
||||||
ProfileActivityService _profileActivityService,
|
ProfileActivityService profileActivityService,
|
||||||
IEnumerable<IHttpListener> _httpListeners
|
IEnumerable<IHttpListener> httpListeners
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
private readonly HttpConfig _httpConfig = _configServer.GetConfig<HttpConfig>();
|
private readonly HttpConfig _httpConfig = configServer.GetConfig<HttpConfig>();
|
||||||
|
|
||||||
public async Task HandleRequest(HttpContext context)
|
public async Task HandleRequest(HttpContext context)
|
||||||
{
|
{
|
||||||
if (context.WebSockets.IsWebSocketRequest)
|
if (context.WebSockets.IsWebSocketRequest)
|
||||||
{
|
{
|
||||||
await _webSocketServer.OnConnection(context);
|
await webSocketServer.OnConnection(context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ public class HttpServer(
|
|||||||
: MongoId.Empty();
|
: MongoId.Empty();
|
||||||
if (!string.IsNullOrEmpty(sessionIdString))
|
if (!string.IsNullOrEmpty(sessionIdString))
|
||||||
{
|
{
|
||||||
_profileActivityService.SetActivityTimestamp(sessionId);
|
profileActivityService.SetActivityTimestamp(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract header for original IP detection
|
// Extract header for original IP detection
|
||||||
@@ -50,7 +50,7 @@ public class HttpServer(
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var listener = _httpListeners.FirstOrDefault(l => l.CanHandle(sessionId, context.Request));
|
var listener = httpListeners.FirstOrDefault(l => l.CanHandle(sessionId, context.Request));
|
||||||
|
|
||||||
if (listener != null)
|
if (listener != null)
|
||||||
{
|
{
|
||||||
@@ -59,9 +59,9 @@ public class HttpServer(
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Critical("Error handling request: " + context.Request.Path);
|
logger.Critical("Error handling request: " + context.Request.Path);
|
||||||
_logger.Critical(ex.Message);
|
logger.Critical(ex.Message);
|
||||||
_logger.Critical(ex.StackTrace);
|
logger.Critical(ex.StackTrace);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
throw; // added this so we can debug something.
|
throw; // added this so we can debug something.
|
||||||
#endif
|
#endif
|
||||||
@@ -80,11 +80,11 @@ public class HttpServer(
|
|||||||
{
|
{
|
||||||
if (isLocalRequest)
|
if (isLocalRequest)
|
||||||
{
|
{
|
||||||
_logger.Info(_serverLocalisationService.GetText("client_request", context.Request.Path.Value));
|
logger.Info(serverLocalisationService.GetText("client_request", context.Request.Path.Value));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Info(_serverLocalisationService.GetText("client_request_ip", new { ip = clientIp, url = context.Request.Path.Value }));
|
logger.Info(serverLocalisationService.GetText("client_request_ip", new { ip = clientIp, url = context.Request.Path.Value }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,24 +13,24 @@ namespace SPTarkov.Server.Core.Servers;
|
|||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class RagfairServer(
|
public class RagfairServer(
|
||||||
ISptLogger<RagfairServer> _logger,
|
ISptLogger<RagfairServer> logger,
|
||||||
TimeUtil timeUtil,
|
TimeUtil timeUtil,
|
||||||
RagfairOfferService _ragfairOfferService,
|
RagfairOfferService ragfairOfferService,
|
||||||
RagfairCategoriesService _ragfairCategoriesService,
|
RagfairCategoriesService ragfairCategoriesService,
|
||||||
RagfairRequiredItemsService _ragfairRequiredItemsService,
|
RagfairRequiredItemsService ragfairRequiredItemsService,
|
||||||
ServerLocalisationService _serverLocalisationService,
|
ServerLocalisationService serverLocalisationService,
|
||||||
RagfairOfferGenerator _ragfairOfferGenerator,
|
RagfairOfferGenerator ragfairOfferGenerator,
|
||||||
RagfairOfferHolder _ragfairOfferHolder,
|
RagfairOfferHolder ragfairOfferHolder,
|
||||||
ConfigServer _configServer,
|
ConfigServer configServer,
|
||||||
ICloner cloner
|
ICloner cloner
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected readonly RagfairConfig _ragfairConfig = _configServer.GetConfig<RagfairConfig>();
|
protected readonly RagfairConfig _ragfairConfig = configServer.GetConfig<RagfairConfig>();
|
||||||
|
|
||||||
public void Load()
|
public void Load()
|
||||||
{
|
{
|
||||||
_logger.Info(_serverLocalisationService.GetText("ragfair-generating_offers"));
|
logger.Info(serverLocalisationService.GetText("ragfair-generating_offers"));
|
||||||
_ragfairOfferGenerator.GenerateDynamicOffers();
|
ragfairOfferGenerator.GenerateDynamicOffers();
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public class RagfairServer(
|
|||||||
ProcessExpiredFleaOffers();
|
ProcessExpiredFleaOffers();
|
||||||
|
|
||||||
// Update requirements now the offers have been expired/regenerated to ensure they're accurate
|
// Update requirements now the offers have been expired/regenerated to ensure they're accurate
|
||||||
_ragfairRequiredItemsService.BuildRequiredItemTable();
|
ragfairRequiredItemsService.BuildRequiredItemTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RefreshTraderOffers()
|
protected void RefreshTraderOffers()
|
||||||
@@ -50,10 +50,10 @@ public class RagfairServer(
|
|||||||
foreach (var traderId in tradersToProcess)
|
foreach (var traderId in tradersToProcess)
|
||||||
{
|
{
|
||||||
// Each trader has its own expiry time
|
// Each trader has its own expiry time
|
||||||
if (_ragfairOfferService.TraderOffersNeedRefreshing(traderId))
|
if (ragfairOfferService.TraderOffersNeedRefreshing(traderId))
|
||||||
{
|
{
|
||||||
// Trader has passed its offer expiry time, update stock and reset offer times
|
// Trader has passed its offer expiry time, update stock and reset offer times
|
||||||
_ragfairOfferGenerator.GenerateFleaOffersForTrader(traderId);
|
ragfairOfferGenerator.GenerateFleaOffersForTrader(traderId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,18 +61,18 @@ public class RagfairServer(
|
|||||||
private void ProcessExpiredFleaOffers()
|
private void ProcessExpiredFleaOffers()
|
||||||
{
|
{
|
||||||
// Regenerate expired offers when over timestamp threshold
|
// Regenerate expired offers when over timestamp threshold
|
||||||
_ragfairOfferHolder.FlagExpiredOffersAfterDate(timeUtil.GetTimeStamp());
|
ragfairOfferHolder.FlagExpiredOffersAfterDate(timeUtil.GetTimeStamp());
|
||||||
|
|
||||||
if (!_ragfairOfferService.EnoughExpiredOffersExistToProcess())
|
if (!ragfairOfferService.EnoughExpiredOffersExistToProcess())
|
||||||
{
|
{
|
||||||
// Not enough expired offers to process, exit
|
// Not enough expired offers to process, exit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must occur BEFORE "RemoveExpiredOffers" + clone items as they'll be purged by `RemoveExpiredOffers()`
|
// Must occur BEFORE "RemoveExpiredOffers" + clone items as they'll be purged by `RemoveExpiredOffers()`
|
||||||
var expiredOfferItemsClone = cloner.Clone(_ragfairOfferHolder.GetExpiredOfferItems());
|
var expiredOfferItemsClone = cloner.Clone(ragfairOfferHolder.GetExpiredOfferItems());
|
||||||
|
|
||||||
_ragfairOfferService.RemoveExpiredOffers();
|
ragfairOfferService.RemoveExpiredOffers();
|
||||||
|
|
||||||
// Force a cleanup+compact now all the expired offers are gone
|
// Force a cleanup+compact now all the expired offers are gone
|
||||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, true, true);
|
GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, true, true);
|
||||||
@@ -80,7 +80,7 @@ public class RagfairServer(
|
|||||||
if (expiredOfferItemsClone is not null)
|
if (expiredOfferItemsClone is not null)
|
||||||
{
|
{
|
||||||
// Replace the expired offers with new ones
|
// Replace the expired offers with new ones
|
||||||
_ragfairOfferGenerator.GenerateDynamicOffers(expiredOfferItemsClone);
|
ragfairOfferGenerator.GenerateDynamicOffers(expiredOfferItemsClone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ public class RagfairServer(
|
|||||||
IEnumerable<RagfairOffer> offers
|
IEnumerable<RagfairOffer> offers
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return _ragfairCategoriesService.GetCategoriesFromOffers(offers, searchRequestData, fleaUnlocked);
|
return ragfairCategoriesService.GetCategoriesFromOffers(offers, searchRequestData, fleaUnlocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -108,12 +108,12 @@ public class RagfairServer(
|
|||||||
/// <param name="offerId"> OfferID to hide </param>
|
/// <param name="offerId"> OfferID to hide </param>
|
||||||
public void HideOffer(MongoId offerId)
|
public void HideOffer(MongoId offerId)
|
||||||
{
|
{
|
||||||
var offers = _ragfairOfferService.GetOffers();
|
var offers = ragfairOfferService.GetOffers();
|
||||||
var offer = offers.FirstOrDefault(x => x.Id == offerId);
|
var offer = offers.FirstOrDefault(x => x.Id == offerId);
|
||||||
|
|
||||||
if (offer is null)
|
if (offer is null)
|
||||||
{
|
{
|
||||||
_logger.Error(_serverLocalisationService.GetText("ragfair-offer_not_found_unable_to_hide", offerId));
|
logger.Error(serverLocalisationService.GetText("ragfair-offer_not_found_unable_to_hide", offerId));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -123,26 +123,26 @@ public class RagfairServer(
|
|||||||
|
|
||||||
public RagfairOffer? GetOffer(MongoId offerId)
|
public RagfairOffer? GetOffer(MongoId offerId)
|
||||||
{
|
{
|
||||||
return _ragfairOfferService.GetOfferByOfferId(offerId);
|
return ragfairOfferService.GetOfferByOfferId(offerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RagfairOffer> GetOffers()
|
public List<RagfairOffer> GetOffers()
|
||||||
{
|
{
|
||||||
return _ragfairOfferService.GetOffers();
|
return ragfairOfferService.GetOffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReduceOfferQuantity(MongoId offerId, int amount)
|
public void ReduceOfferQuantity(MongoId offerId, int amount)
|
||||||
{
|
{
|
||||||
_ragfairOfferService.ReduceOfferQuantity(offerId, amount);
|
ragfairOfferService.ReduceOfferQuantity(offerId, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DoesOfferExist(MongoId offerId)
|
public bool DoesOfferExist(MongoId offerId)
|
||||||
{
|
{
|
||||||
return _ragfairOfferService.DoesOfferExist(offerId);
|
return ragfairOfferService.DoesOfferExist(offerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddPlayerOffers()
|
public void AddPlayerOffers()
|
||||||
{
|
{
|
||||||
_ragfairOfferService.AddPlayerOffers();
|
ragfairOfferService.AddPlayerOffers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
|||||||
namespace SPTarkov.Server.Core.Servers;
|
namespace SPTarkov.Server.Core.Servers;
|
||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocketConnectionHandler, ISptLogger<WebSocketServer> _logger)
|
public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> webSocketConnectionHandler, ISptLogger<WebSocketServer> logger)
|
||||||
{
|
{
|
||||||
public async Task OnConnection(HttpContext httpContext)
|
public async Task OnConnection(HttpContext httpContext)
|
||||||
{
|
{
|
||||||
@@ -18,7 +18,7 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
|
|
||||||
private async Task HandleWebSocket(HttpContext context, WebSocket webSocket)
|
private async Task HandleWebSocket(HttpContext context, WebSocket webSocket)
|
||||||
{
|
{
|
||||||
var socketHandlers = _webSocketConnectionHandler.Where(wsh => context.Request.Path.Value.Contains(wsh.GetHookUrl()));
|
var socketHandlers = webSocketConnectionHandler.Where(wsh => context.Request.Path.Value.Contains(wsh.GetHookUrl()));
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
var wsToken = cts.Token;
|
var wsToken = cts.Token;
|
||||||
@@ -27,34 +27,34 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
{
|
{
|
||||||
var message =
|
var message =
|
||||||
$"Socket connection received for url {context.Request.Path.Value}, but there is no websocket handler configured for it!";
|
$"Socket connection received for url {context.Request.Path.Value}, but there is no websocket handler configured for it!";
|
||||||
_logger.Debug(message);
|
logger.Debug(message);
|
||||||
await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, message, CancellationToken.None);
|
await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, message, CancellationToken.None);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var webSocketIdContext = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
|
var webSocketIdContext = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] Notifying handlers of new websocket connection opening with reference {webSocketIdContext}");
|
logger.Debug($"[WS] Notifying handlers of new websocket connection opening with reference {webSocketIdContext}");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var wsh in socketHandlers)
|
foreach (var wsh in socketHandlers)
|
||||||
{
|
{
|
||||||
if (webSocket.State == WebSocketState.Open)
|
if (webSocket.State == WebSocketState.Open)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"WebSocketHandler \"{wsh.GetSocketId()}\" connected");
|
logger.Debug($"WebSocketHandler \"{wsh.GetSocketId()}\" connected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await wsh.OnConnection(webSocket, context, webSocketIdContext);
|
await wsh.OnConnection(webSocket, context, webSocketIdContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] Starting read loop for websocket reference {webSocketIdContext}");
|
logger.Debug($"[WS] Starting read loop for websocket reference {webSocketIdContext}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var thread = Task.Factory.StartNew(
|
var thread = Task.Factory.StartNew(
|
||||||
@@ -98,7 +98,7 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
// If this is not handled an exception is thrown on the client
|
// If this is not handled an exception is thrown on the client
|
||||||
if (result.MessageType == WebSocketMessageType.Close)
|
if (result.MessageType == WebSocketMessageType.Close)
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] WebSocket reference {webSocketIdContext} sent close frame, stopping.");
|
logger.Debug($"[WS] WebSocket reference {webSocketIdContext} sent close frame, stopping.");
|
||||||
await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closing..", wsToken);
|
await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closing..", wsToken);
|
||||||
socketClosing = true;
|
socketClosing = true;
|
||||||
break;
|
break;
|
||||||
@@ -108,9 +108,9 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
|
|
||||||
if (result.EndOfMessage)
|
if (result.EndOfMessage)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
logger.Debug(
|
||||||
$"[WS] Read loop for websocket reference {webSocketIdContext} received new message. Notifying socket handlers."
|
$"[WS] Read loop for websocket reference {webSocketIdContext} received new message. Notifying socket handlers."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -134,9 +134,9 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
var counter = 0;
|
var counter = 0;
|
||||||
while (webSocket.State == WebSocketState.Open)
|
while (webSocket.State == WebSocketState.Open)
|
||||||
{
|
{
|
||||||
if (counter == 30 && _logger.IsLogEnabled(LogLevel.Debug))
|
if (counter == 30 && logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
logger.Debug(
|
||||||
$"[WS] Websocket keep alive for reference {webSocketIdContext}. Thread state {thread.Status}. Websocket state {webSocket.State}"
|
$"[WS] Websocket keep alive for reference {webSocketIdContext}. Thread state {thread.Status}. Websocket state {webSocket.State}"
|
||||||
);
|
);
|
||||||
counter = 0;
|
counter = 0;
|
||||||
@@ -150,9 +150,9 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] State for websocket reference {webSocketIdContext} is now {webSocket.State}, closing");
|
logger.Debug($"[WS] State for websocket reference {webSocketIdContext} is now {webSocket.State}, closing");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect has been received, cancel the token and send OnClose to the relevant WebSockets.
|
// Disconnect has been received, cancel the token and send OnClose to the relevant WebSockets.
|
||||||
@@ -160,17 +160,17 @@ public class WebSocketServer(IEnumerable<IWebSocketConnectionHandler> _webSocket
|
|||||||
{
|
{
|
||||||
await cts.CancelAsync();
|
await cts.CancelAsync();
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] OnClose for websocket reference {webSocketIdContext} requested");
|
logger.Debug($"[WS] OnClose for websocket reference {webSocketIdContext} requested");
|
||||||
}
|
}
|
||||||
|
|
||||||
await wsh.OnClose(webSocket, context, webSocketIdContext);
|
await wsh.OnClose(webSocket, context, webSocketIdContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] Websocket reference {webSocketIdContext} fully closed.");
|
logger.Debug($"[WS] Websocket reference {webSocketIdContext} fully closed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,10 +6,10 @@ using SPTarkov.Server.Core.Models.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Servers.Ws.Message;
|
namespace SPTarkov.Server.Core.Servers.Ws.Message;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class DefaultSptWebSocketMessageHandler(ISptLogger<DefaultSptWebSocketMessageHandler> _logger) : ISptWebSocketMessageHandler
|
public class DefaultSptWebSocketMessageHandler(ISptLogger<DefaultSptWebSocketMessageHandler> logger) : ISptWebSocketMessageHandler
|
||||||
{
|
{
|
||||||
public async Task OnSptMessage(string sessionID, WebSocket client, byte[] rawData)
|
public async Task OnSptMessage(string sessionID, WebSocket client, byte[] rawData)
|
||||||
{
|
{
|
||||||
_logger.Debug($"[{sessionID}] SPT message received: {Encoding.UTF8.GetString(rawData)}");
|
logger.Debug($"[{sessionID}] SPT message received: {Encoding.UTF8.GetString(rawData)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ namespace SPTarkov.Server.Core.Servers.Ws;
|
|||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class SptWebSocketConnectionHandler(
|
public class SptWebSocketConnectionHandler(
|
||||||
ISptLogger<SptWebSocketConnectionHandler> _logger,
|
ISptLogger<SptWebSocketConnectionHandler> logger,
|
||||||
ServerLocalisationService _serverLocalisationService,
|
ServerLocalisationService serverLocalisationService,
|
||||||
JsonUtil _jsonUtil,
|
JsonUtil jsonUtil,
|
||||||
ProfileHelper _profileHelper,
|
ProfileHelper profileHelper,
|
||||||
IEnumerable<ISptWebSocketMessageHandler> _messageHandlers
|
IEnumerable<ISptWebSocketMessageHandler> messageHandlers
|
||||||
) : IWebSocketConnectionHandler
|
) : IWebSocketConnectionHandler
|
||||||
{
|
{
|
||||||
protected readonly Dictionary<string, Dictionary<string, WebSocket>> _sockets = new();
|
protected readonly Dictionary<string, Dictionary<string, WebSocket>> _sockets = new();
|
||||||
@@ -38,11 +38,11 @@ public class SptWebSocketConnectionHandler(
|
|||||||
{
|
{
|
||||||
var splitUrl = context.Request.Path.Value.Split("/");
|
var splitUrl = context.Request.Path.Value.Split("/");
|
||||||
var sessionID = splitUrl.Last();
|
var sessionID = splitUrl.Last();
|
||||||
var playerProfile = _profileHelper.GetFullProfile(sessionID);
|
var playerProfile = profileHelper.GetFullProfile(sessionID);
|
||||||
var playerInfoText = $"{playerProfile.ProfileInfo.Username} ({sessionID})";
|
var playerInfoText = $"{playerProfile.ProfileInfo.Username} ({sessionID})";
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] Websocket connect for player {playerInfoText} started with context {sessionIdContext}");
|
logger.Debug($"[WS] Websocket connect for player {playerInfoText} started with context {sessionIdContext}");
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (_socketsLock)
|
lock (_socketsLock)
|
||||||
@@ -51,10 +51,10 @@ public class SptWebSocketConnectionHandler(
|
|||||||
{
|
{
|
||||||
if (sessionSockets.Any())
|
if (sessionSockets.Any())
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
logger.Debug(
|
||||||
_serverLocalisationService.GetText(
|
serverLocalisationService.GetText(
|
||||||
"websocket-player_reconnect",
|
"websocket-player_reconnect",
|
||||||
new { sessionId = playerInfoText, contextId = sessionIdContext }
|
new { sessionId = playerInfoText, contextId = sessionIdContext }
|
||||||
)
|
)
|
||||||
@@ -69,10 +69,10 @@ public class SptWebSocketConnectionHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
sessionSockets.Add(sessionIdContext, ws);
|
sessionSockets.Add(sessionIdContext, ws);
|
||||||
if (_logger.IsLogEnabled(LogLevel.Info))
|
if (logger.IsLogEnabled(LogLevel.Info))
|
||||||
{
|
{
|
||||||
_logger.Info(
|
logger.Info(
|
||||||
_serverLocalisationService.GetText(
|
serverLocalisationService.GetText(
|
||||||
"websocket-player_connected",
|
"websocket-player_connected",
|
||||||
new { sessionId = playerInfoText, contextId = sessionIdContext }
|
new { sessionId = playerInfoText, contextId = sessionIdContext }
|
||||||
)
|
)
|
||||||
@@ -87,12 +87,12 @@ public class SptWebSocketConnectionHandler(
|
|||||||
{
|
{
|
||||||
var splitUrl = context.Request.Path.Value.Split("/");
|
var splitUrl = context.Request.Path.Value.Split("/");
|
||||||
var sessionID = splitUrl.Last();
|
var sessionID = splitUrl.Last();
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"[WS] Message for session {sessionID} received. Notifying message handlers.");
|
logger.Debug($"[WS] Message for session {sessionID} received. Notifying message handlers.");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var sptWebSocketMessageHandler in _messageHandlers)
|
foreach (var sptWebSocketMessageHandler in messageHandlers)
|
||||||
{
|
{
|
||||||
await sptWebSocketMessageHandler.OnSptMessage(sessionID, ws, receivedMessage);
|
await sptWebSocketMessageHandler.OnSptMessage(sessionID, ws, receivedMessage);
|
||||||
}
|
}
|
||||||
@@ -105,40 +105,40 @@ public class SptWebSocketConnectionHandler(
|
|||||||
|
|
||||||
lock (_socketsLock)
|
lock (_socketsLock)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Attempting to close websocket session {sessionID} with context {sessionIdContext}");
|
logger.Debug($"Attempting to close websocket session {sessionID} with context {sessionIdContext}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sockets.TryGetValue(sessionID, out var sessionSockets) && sessionSockets.Any())
|
if (_sockets.TryGetValue(sessionID, out var sessionSockets) && sessionSockets.Any())
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Websockets for session {sessionID} entry matched, attempting to find context {sessionIdContext}");
|
logger.Debug($"Websockets for session {sessionID} entry matched, attempting to find context {sessionIdContext}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sessionSockets.TryGetValue(sessionIdContext, out _) && _logger.IsLogEnabled(LogLevel.Info))
|
if (!sessionSockets.TryGetValue(sessionIdContext, out _) && logger.IsLogEnabled(LogLevel.Info))
|
||||||
{
|
{
|
||||||
_logger.Info(
|
logger.Info(
|
||||||
$"[ws] The websocket session {sessionID} with reference: {sessionIdContext} has already been removed or reconnected"
|
$"[ws] The websocket session {sessionID} with reference: {sessionIdContext} has already been removed or reconnected"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sessionSockets.Remove(sessionIdContext);
|
sessionSockets.Remove(sessionIdContext);
|
||||||
if (_logger.IsLogEnabled(LogLevel.Info))
|
if (logger.IsLogEnabled(LogLevel.Info))
|
||||||
{
|
{
|
||||||
var playerProfile = _profileHelper.GetFullProfile(sessionID);
|
var playerProfile = profileHelper.GetFullProfile(sessionID);
|
||||||
var playerInfoText = $"{playerProfile.ProfileInfo.Username} ({sessionID})";
|
var playerInfoText = $"{playerProfile.ProfileInfo.Username} ({sessionID})";
|
||||||
_logger.Info($"[ws] player: {playerInfoText} {sessionIdContext} has disconnected");
|
logger.Info($"[ws] player: {playerInfoText} {sessionIdContext} has disconnected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
logger.Debug(
|
||||||
$"Websocket for session {sessionID} with context {sessionIdContext} does not exist on the socket map, nothing was removed"
|
$"Websocket for session {sessionID} with context {sessionIdContext} does not exist on the socket map, nothing was removed"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -165,47 +165,47 @@ public class SptWebSocketConnectionHandler(
|
|||||||
{
|
{
|
||||||
var webSockets = GetSessionWebSocket(sessionID);
|
var webSockets = GetSessionWebSocket(sessionID);
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Send message for {sessionID} matched {webSockets.Count()} websockets. Messages being sent");
|
logger.Debug($"Send message for {sessionID} matched {webSockets.Count()} websockets. Messages being sent");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var webSocket in webSockets)
|
foreach (var webSocket in webSockets)
|
||||||
{
|
{
|
||||||
var sendTask = webSocket.SendAsync(
|
var sendTask = webSocket.SendAsync(
|
||||||
Encoding.UTF8.GetBytes(_jsonUtil.Serialize(output, output.GetType())),
|
Encoding.UTF8.GetBytes(jsonUtil.Serialize(output, output.GetType())),
|
||||||
WebSocketMessageType.Text,
|
WebSocketMessageType.Text,
|
||||||
true,
|
true,
|
||||||
CancellationToken.None
|
CancellationToken.None
|
||||||
);
|
);
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Send message for {sessionID} on websocket async started");
|
logger.Debug($"Send message for {sessionID} on websocket async started");
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTask.Wait();
|
sendTask.Wait();
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Send message for {sessionID} on websocket async finished");
|
logger.Debug($"Send message for {sessionID} on websocket async finished");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(_serverLocalisationService.GetText("websocket-message_sent"));
|
logger.Debug(serverLocalisationService.GetText("websocket-message_sent"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(_serverLocalisationService.GetText("websocket-not_ready_message_not_sent", sessionID));
|
logger.Debug(serverLocalisationService.GetText("websocket-not_ready_message_not_sent", sessionID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception err)
|
catch (Exception err)
|
||||||
{
|
{
|
||||||
_logger.Error(_serverLocalisationService.GetText("websocket-message_send_failed_with_error"), err);
|
logger.Error(serverLocalisationService.GetText("websocket-message_send_failed_with_error"), err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ namespace SPTarkov.Server.Core.Services;
|
|||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class AirdropService(
|
public class AirdropService(
|
||||||
ISptLogger<AirdropService> _logger,
|
ISptLogger<AirdropService> logger,
|
||||||
ConfigServer configServer,
|
ConfigServer configServer,
|
||||||
LootGenerator _lootGenerator,
|
LootGenerator lootGenerator,
|
||||||
DatabaseService databaseService,
|
DatabaseService databaseService,
|
||||||
WeightedRandomHelper _weightedRandomHelper,
|
WeightedRandomHelper weightedRandomHelper,
|
||||||
ServerLocalisationService _serverLocalisationService,
|
ServerLocalisationService serverLocalisationService,
|
||||||
ItemFilterService _itemFilterService,
|
ItemFilterService itemFilterService,
|
||||||
ItemHelper _itemHelper
|
ItemHelper itemHelper
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected readonly AirdropConfig _airdropConfig = configServer.GetConfig<AirdropConfig>();
|
protected readonly AirdropConfig _airdropConfig = configServer.GetConfig<AirdropConfig>();
|
||||||
@@ -36,7 +36,7 @@ public class AirdropService(
|
|||||||
return GenerateAirdropLoot(customAirdropInformation);
|
return GenerateAirdropLoot(customAirdropInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Warning(_serverLocalisationService.GetText("airdrop-unable_to_find_container_id_generating_random", request.ContainerId));
|
logger.Warning(serverLocalisationService.GetText("airdrop-unable_to_find_container_id_generating_random", request.ContainerId));
|
||||||
|
|
||||||
return GenerateAirdropLoot();
|
return GenerateAirdropLoot();
|
||||||
}
|
}
|
||||||
@@ -51,9 +51,9 @@ public class AirdropService(
|
|||||||
public GetAirdropLootResponse GenerateAirdropLoot(SptAirdropTypeEnum? forcedAirdropType = null)
|
public GetAirdropLootResponse GenerateAirdropLoot(SptAirdropTypeEnum? forcedAirdropType = null)
|
||||||
{
|
{
|
||||||
var airdropType = forcedAirdropType ?? ChooseAirdropType();
|
var airdropType = forcedAirdropType ?? ChooseAirdropType();
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Chose: {airdropType} for airdrop loot");
|
logger.Debug($"Chose: {airdropType} for airdrop loot");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common/weapon/etc
|
// Common/weapon/etc
|
||||||
@@ -61,8 +61,8 @@ public class AirdropService(
|
|||||||
|
|
||||||
// generate loot to put into airdrop crate
|
// generate loot to put into airdrop crate
|
||||||
var crateLootPool = airdropConfig.UseForcedLoot.GetValueOrDefault(false)
|
var crateLootPool = airdropConfig.UseForcedLoot.GetValueOrDefault(false)
|
||||||
? _lootGenerator.CreateForcedLoot(airdropConfig.ForcedLoot)
|
? lootGenerator.CreateForcedLoot(airdropConfig.ForcedLoot)
|
||||||
: _lootGenerator.CreateRandomLoot(airdropConfig);
|
: lootGenerator.CreateRandomLoot(airdropConfig);
|
||||||
|
|
||||||
// Create airdrop crate and add to result in first spot
|
// Create airdrop crate and add to result in first spot
|
||||||
var airdropCrateItem = GetAirdropCrateItem(airdropType);
|
var airdropCrateItem = GetAirdropCrateItem(airdropType);
|
||||||
@@ -106,13 +106,13 @@ public class AirdropService(
|
|||||||
var lootResult = new List<List<Item>>();
|
var lootResult = new List<List<Item>>();
|
||||||
|
|
||||||
// Get 2d mapping of container
|
// Get 2d mapping of container
|
||||||
var containerMap = _itemHelper.GetContainerMapping(container.Template);
|
var containerMap = itemHelper.GetContainerMapping(container.Template);
|
||||||
|
|
||||||
var failedToFitAttemptCount = 0;
|
var failedToFitAttemptCount = 0;
|
||||||
foreach (var itemAndChildren in crateLootPool)
|
foreach (var itemAndChildren in crateLootPool)
|
||||||
{
|
{
|
||||||
// Get x/y size of item (weapons get larger with children attached)
|
// Get x/y size of item (weapons get larger with children attached)
|
||||||
var itemSize = _itemHelper.GetItemSize(itemAndChildren, itemAndChildren[0].Id);
|
var itemSize = itemHelper.GetItemSize(itemAndChildren, itemAndChildren[0].Id);
|
||||||
|
|
||||||
// Look for open slot to put chosen item into
|
// Look for open slot to put chosen item into
|
||||||
var result = containerMap.FindSlotForItem(itemSize.Width, itemSize.Height);
|
var result = containerMap.FindSlotForItem(itemSize.Width, itemSize.Height);
|
||||||
@@ -136,7 +136,7 @@ public class AirdropService(
|
|||||||
if (failedToFitAttemptCount > 3)
|
if (failedToFitAttemptCount > 3)
|
||||||
// 3 attempts to fit an item, container is probably full, stop trying to add more
|
// 3 attempts to fit an item, container is probably full, stop trying to add more
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
logger.Debug(
|
||||||
$"Airdrop is too full of loot to add: {itemAndChildren[0].Template} after {failedToFitAttemptCount} attempts, stopped adding more"
|
$"Airdrop is too full of loot to add: {itemAndChildren[0].Template} after {failedToFitAttemptCount} attempts, stopped adding more"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -196,7 +196,7 @@ public class AirdropService(
|
|||||||
{
|
{
|
||||||
var possibleAirdropTypes = _airdropConfig.AirdropTypeWeightings;
|
var possibleAirdropTypes = _airdropConfig.AirdropTypeWeightings;
|
||||||
|
|
||||||
return _weightedRandomHelper.GetWeightedValue(possibleAirdropTypes);
|
return weightedRandomHelper.GetWeightedValue(possibleAirdropTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -208,7 +208,7 @@ public class AirdropService(
|
|||||||
{
|
{
|
||||||
if (!_airdropConfig.Loot.TryGetValue(airdropType.ToString(), out var lootSettingsByType))
|
if (!_airdropConfig.Loot.TryGetValue(airdropType.ToString(), out var lootSettingsByType))
|
||||||
{
|
{
|
||||||
_logger.Error(_serverLocalisationService.GetText("location-unable_to_find_airdrop_drop_config_of_type", airdropType));
|
logger.Error(serverLocalisationService.GetText("location-unable_to_find_airdrop_drop_config_of_type", airdropType));
|
||||||
|
|
||||||
// TODO: Get Radar airdrop to work. Atm Radar will default to common supply drop (mixed)
|
// TODO: Get Radar airdrop to work. Atm Radar will default to common supply drop (mixed)
|
||||||
// Default to common
|
// Default to common
|
||||||
@@ -216,17 +216,17 @@ public class AirdropService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all items that match the blacklisted types and fold into item blacklist
|
// Get all items that match the blacklisted types and fold into item blacklist
|
||||||
var itemTypeBlacklist = _itemFilterService.GetItemRewardBaseTypeBlacklist();
|
var itemTypeBlacklist = itemFilterService.GetItemRewardBaseTypeBlacklist();
|
||||||
var itemsMatchingTypeBlacklist = databaseService
|
var itemsMatchingTypeBlacklist = databaseService
|
||||||
.GetItems()
|
.GetItems()
|
||||||
.Where(kvp => !kvp.Value.Parent.IsEmpty)
|
.Where(kvp => !kvp.Value.Parent.IsEmpty)
|
||||||
.Where(kvp => _itemHelper.IsOfBaseclasses(kvp.Value.Parent, itemTypeBlacklist))
|
.Where(kvp => itemHelper.IsOfBaseclasses(kvp.Value.Parent, itemTypeBlacklist))
|
||||||
.Select(kvp => kvp.Key)
|
.Select(kvp => kvp.Key)
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
var itemBlacklist = new HashSet<MongoId>();
|
var itemBlacklist = new HashSet<MongoId>();
|
||||||
itemBlacklist.UnionWith(lootSettingsByType.ItemBlacklist);
|
itemBlacklist.UnionWith(lootSettingsByType.ItemBlacklist);
|
||||||
itemBlacklist.UnionWith(_itemFilterService.GetItemRewardBlacklist());
|
itemBlacklist.UnionWith(itemFilterService.GetItemRewardBlacklist());
|
||||||
itemBlacklist.UnionWith(_itemFilterService.GetBossItems());
|
itemBlacklist.UnionWith(itemFilterService.GetBossItems());
|
||||||
itemBlacklist.UnionWith(itemsMatchingTypeBlacklist);
|
itemBlacklist.UnionWith(itemsMatchingTypeBlacklist);
|
||||||
|
|
||||||
return new AirdropLootRequest
|
return new AirdropLootRequest
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ public class BackupService
|
|||||||
|
|
||||||
// Runs Init() every x minutes
|
// Runs Init() every x minutes
|
||||||
protected Timer _backupIntervalTimer;
|
protected Timer _backupIntervalTimer;
|
||||||
protected readonly FileUtil _fileUtil;
|
|
||||||
protected readonly JsonUtil _jsonUtil;
|
protected readonly FileUtil FileUtil;
|
||||||
protected readonly ISptLogger<BackupService> _logger;
|
protected readonly JsonUtil JsonUtil;
|
||||||
protected readonly TimeUtil _timeUtil;
|
protected readonly ISptLogger<BackupService> Logger;
|
||||||
protected readonly IReadOnlyList<SptMod> _loadedMods;
|
protected readonly TimeUtil TimeUtil;
|
||||||
|
protected readonly IReadOnlyList<SptMod> LoadedMods;
|
||||||
|
|
||||||
public BackupService(
|
public BackupService(
|
||||||
ISptLogger<BackupService> logger,
|
ISptLogger<BackupService> logger,
|
||||||
@@ -34,11 +35,11 @@ public class BackupService
|
|||||||
FileUtil fileUtil
|
FileUtil fileUtil
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
Logger = logger;
|
||||||
_jsonUtil = jsonUtil;
|
JsonUtil = jsonUtil;
|
||||||
_timeUtil = timeUtil;
|
TimeUtil = timeUtil;
|
||||||
_fileUtil = fileUtil;
|
FileUtil = fileUtil;
|
||||||
_loadedMods = loadedMods;
|
LoadedMods = loadedMods;
|
||||||
|
|
||||||
_activeServerMods = GetActiveServerMods();
|
_activeServerMods = GetActiveServerMods();
|
||||||
_backupConfig = configServer.GetConfig<BackupConfig>();
|
_backupConfig = configServer.GetConfig<BackupConfig>();
|
||||||
@@ -66,7 +67,7 @@ public class BackupService
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error($"Profile backup failed: {ex.Message}, {ex.StackTrace}");
|
Logger.Error($"Profile backup failed: {ex.Message}, {ex.StackTrace}");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
@@ -93,19 +94,19 @@ public class BackupService
|
|||||||
List<string> currentProfilePaths;
|
List<string> currentProfilePaths;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
currentProfilePaths = _fileUtil.GetFiles(_profileDir);
|
currentProfilePaths = FileUtil.GetFiles(_profileDir);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Debug($"Skipping profile backup: Unable to read profiles directory, {ex.Message}");
|
Logger.Debug($"Skipping profile backup: Unable to read profiles directory, {ex.Message}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentProfilePaths.Count == 0)
|
if (currentProfilePaths.Count == 0)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (Logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug("No profiles to backup");
|
Logger.Debug("No profiles to backup");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -113,33 +114,33 @@ public class BackupService
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_fileUtil.CreateDirectory(targetDir);
|
FileUtil.CreateDirectory(targetDir);
|
||||||
|
|
||||||
foreach (var profilePath in currentProfilePaths)
|
foreach (var profilePath in currentProfilePaths)
|
||||||
{
|
{
|
||||||
// Get filename + extension, removing the path
|
// Get filename + extension, removing the path
|
||||||
var profileFileName = _fileUtil.GetFileNameAndExtension(profilePath);
|
var profileFileName = FileUtil.GetFileNameAndExtension(profilePath);
|
||||||
|
|
||||||
// Create absolute path to file
|
// Create absolute path to file
|
||||||
var relativeSourceFilePath = Path.Combine(_profileDir, profileFileName);
|
var relativeSourceFilePath = Path.Combine(_profileDir, profileFileName);
|
||||||
var absoluteDestinationFilePath = Path.Combine(targetDir, profileFileName);
|
var absoluteDestinationFilePath = Path.Combine(targetDir, profileFileName);
|
||||||
if (!_fileUtil.CopyFile(relativeSourceFilePath, absoluteDestinationFilePath))
|
if (!FileUtil.CopyFile(relativeSourceFilePath, absoluteDestinationFilePath))
|
||||||
{
|
{
|
||||||
_logger.Error($"Source file not found: {relativeSourceFilePath}. Cannot copy to: {absoluteDestinationFilePath}");
|
Logger.Error($"Source file not found: {relativeSourceFilePath}. Cannot copy to: {absoluteDestinationFilePath}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a copy of active mods.
|
// Write a copy of active mods.
|
||||||
await _fileUtil.WriteFileAsync(Path.Combine(targetDir, "activeMods.json"), _jsonUtil.Serialize(_activeServerMods));
|
await FileUtil.WriteFileAsync(Path.Combine(targetDir, "activeMods.json"), JsonUtil.Serialize(_activeServerMods));
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (Logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Profile backup created in: {targetDir}");
|
Logger.Debug($"Profile backup created in: {targetDir}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error($"Unable to write to backup profile directory: {ex.Message}");
|
Logger.Error($"Unable to write to backup profile directory: {ex.Message}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +158,9 @@ public class BackupService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (Logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug("Profile backups disabled");
|
Logger.Debug("Profile backups disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -182,7 +183,7 @@ public class BackupService
|
|||||||
/// <returns> The formatted backup date string. </returns>
|
/// <returns> The formatted backup date string. </returns>
|
||||||
protected string GenerateBackupDate()
|
protected string GenerateBackupDate()
|
||||||
{
|
{
|
||||||
return _timeUtil.GetDateTimeNow().ToString("yyyy-MM-dd_HH-mm-ss");
|
return TimeUtil.GetDateTimeNow().ToString("yyyy-MM-dd_HH-mm-ss");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -229,7 +230,7 @@ public class BackupService
|
|||||||
/// <returns> List of sorted backup file paths. </returns>
|
/// <returns> List of sorted backup file paths. </returns>
|
||||||
protected List<string> GetBackupPaths(string dir)
|
protected List<string> GetBackupPaths(string dir)
|
||||||
{
|
{
|
||||||
var backups = _fileUtil.GetDirectories(dir).ToList();
|
var backups = FileUtil.GetDirectories(dir).ToList();
|
||||||
backups.Sort(CompareBackupDates);
|
backups.Sort(CompareBackupDates);
|
||||||
|
|
||||||
return backups;
|
return backups;
|
||||||
@@ -269,7 +270,7 @@ public class BackupService
|
|||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Warning($"Invalid backup folder name format: {folderPath}, [{folderName}]");
|
Logger.Warning($"Invalid backup folder name format: {folderPath}, [{folderName}]");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,11 +284,11 @@ public class BackupService
|
|||||||
var filePathsToDelete = backupFilenames.Select(x => x);
|
var filePathsToDelete = backupFilenames.Select(x => x);
|
||||||
foreach (var pathToDelete in filePathsToDelete)
|
foreach (var pathToDelete in filePathsToDelete)
|
||||||
{
|
{
|
||||||
_fileUtil.DeleteDirectory(Path.Combine(pathToDelete), true);
|
FileUtil.DeleteDirectory(Path.Combine(pathToDelete), true);
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (Logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Deleted old backup: {pathToDelete}");
|
Logger.Debug($"Deleted old backup: {pathToDelete}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,7 +301,7 @@ public class BackupService
|
|||||||
{
|
{
|
||||||
List<string> result = [];
|
List<string> result = [];
|
||||||
|
|
||||||
foreach (var mod in _loadedMods)
|
foreach (var mod in LoadedMods)
|
||||||
{
|
{
|
||||||
result.Add($"{mod.ModMetadata.Author} - {mod.ModMetadata.Version}");
|
result.Add($"{mod.ModMetadata.Author} - {mod.ModMetadata.Version}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Microsoft.Extensions.Hosting;
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
using SPTarkov.Server.Core.DI;
|
using SPTarkov.Server.Core.DI;
|
||||||
using SPTarkov.Server.Core.Extensions;
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
|
||||||
using SPTarkov.Server.Core.Models.Utils;
|
using SPTarkov.Server.Core.Models.Utils;
|
||||||
using SPTarkov.Server.Core.Servers;
|
using SPTarkov.Server.Core.Servers;
|
||||||
using SPTarkov.Server.Core.Services;
|
using SPTarkov.Server.Core.Services;
|
||||||
@@ -13,47 +12,45 @@ namespace SPTarkov.Server.Core.Utils;
|
|||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class App(
|
public class App(
|
||||||
IServiceProvider _serviceProvider,
|
IServiceProvider serviceProvider,
|
||||||
ISptLogger<App> _logger,
|
ISptLogger<App> logger,
|
||||||
TimeUtil _timeUtil,
|
TimeUtil timeUtil,
|
||||||
RandomUtil _randomUtil,
|
RandomUtil randomUtil,
|
||||||
ServerLocalisationService _serverLocalisationService,
|
ServerLocalisationService serverLocalisationService,
|
||||||
ConfigServer _configServer,
|
HttpServer httpServer,
|
||||||
HttpServer _httpServer,
|
DatabaseService databaseService,
|
||||||
DatabaseService _databaseService,
|
IHostApplicationLifetime appLifeTime,
|
||||||
IHostApplicationLifetime _appLifeTime,
|
IEnumerable<IOnLoad> onLoadComponents,
|
||||||
IEnumerable<IOnLoad> _onLoadComponents,
|
IEnumerable<IOnUpdate> onUpdateComponents
|
||||||
IEnumerable<IOnUpdate> _onUpdateComponents
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected readonly CoreConfig _coreConfig = _configServer.GetConfig<CoreConfig>();
|
|
||||||
protected readonly Dictionary<string, long> _onUpdateLastRun = new();
|
protected readonly Dictionary<string, long> _onUpdateLastRun = new();
|
||||||
|
|
||||||
public async Task InitializeAsync()
|
public async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
ServiceLocator.SetServiceProvider(_serviceProvider);
|
ServiceLocator.SetServiceProvider(serviceProvider);
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"OS: {Environment.OSVersion.Version} | {Environment.OSVersion.Platform}");
|
logger.Debug($"OS: {Environment.OSVersion.Version} | {Environment.OSVersion.Platform}");
|
||||||
_logger.Debug($"Ran as admin: {Environment.IsPrivilegedProcess}");
|
logger.Debug($"Ran as admin: {Environment.IsPrivilegedProcess}");
|
||||||
_logger.Debug($"CPU cores: {Environment.ProcessorCount}");
|
logger.Debug($"CPU cores: {Environment.ProcessorCount}");
|
||||||
_logger.Debug($"PATH: {(Environment.ProcessPath ?? "null returned").Encode(EncodeType.BASE64)}");
|
logger.Debug($"PATH: {(Environment.ProcessPath ?? "null returned").Encode(EncodeType.BASE64)}");
|
||||||
_logger.Debug($"Server: {ProgramStatics.SPT_VERSION()}");
|
logger.Debug($"Server: {ProgramStatics.SPT_VERSION()}");
|
||||||
|
|
||||||
// _logger.Debug($"RAM: {(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB");
|
// _logger.Debug($"RAM: {(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB");
|
||||||
|
|
||||||
if (ProgramStatics.BUILD_TIME() != 0)
|
if (ProgramStatics.BUILD_TIME() != 0)
|
||||||
{
|
{
|
||||||
_logger.Debug($"Date: {ProgramStatics.BUILD_TIME()}");
|
logger.Debug($"Date: {ProgramStatics.BUILD_TIME()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug($"Commit: {ProgramStatics.COMMIT()}");
|
logger.Debug($"Commit: {ProgramStatics.COMMIT()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute onLoad callbacks
|
// execute onLoad callbacks
|
||||||
_logger.Info(_serverLocalisationService.GetText("executing_startup_callbacks"));
|
logger.Info(serverLocalisationService.GetText("executing_startup_callbacks"));
|
||||||
foreach (var onLoad in _onLoadComponents)
|
foreach (var onLoad in onLoadComponents)
|
||||||
{
|
{
|
||||||
await onLoad.OnLoad();
|
await onLoad.OnLoad();
|
||||||
}
|
}
|
||||||
@@ -61,36 +58,36 @@ public class App(
|
|||||||
// Discard here, as this task will run indefinitely
|
// Discard here, as this task will run indefinitely
|
||||||
_ = Task.Run(Update);
|
_ = Task.Run(Update);
|
||||||
|
|
||||||
_logger.Success(_serverLocalisationService.GetText("started_webserver_success", _httpServer.ListeningUrl()));
|
logger.Success(serverLocalisationService.GetText("started_webserver_success", httpServer.ListeningUrl()));
|
||||||
_logger.Success(_serverLocalisationService.GetText("websocket-started", _httpServer.ListeningUrl().Replace("https://", "wss://")));
|
logger.Success(serverLocalisationService.GetText("websocket-started", httpServer.ListeningUrl().Replace("https://", "wss://")));
|
||||||
|
|
||||||
_logger.Success(GetRandomisedStartMessage());
|
logger.Success(GetRandomisedStartMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetRandomisedStartMessage()
|
protected string GetRandomisedStartMessage()
|
||||||
{
|
{
|
||||||
if (_randomUtil.GetInt(1, 1000) > 999)
|
if (randomUtil.GetInt(1, 1000) > 999)
|
||||||
{
|
{
|
||||||
return _serverLocalisationService.GetRandomTextThatMatchesPartialKey("server_start_meme_");
|
return serverLocalisationService.GetRandomTextThatMatchesPartialKey("server_start_meme_");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _serverLocalisationService.GetText("server_start_success");
|
return serverLocalisationService.GetText("server_start_success");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task Update()
|
protected async Task Update()
|
||||||
{
|
{
|
||||||
while (!_appLifeTime.ApplicationStopping.IsCancellationRequested)
|
while (!appLifeTime.ApplicationStopping.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
// If the server has failed to start, skip any update calls
|
// If the server has failed to start, skip any update calls
|
||||||
if (!_databaseService.IsDatabaseValid())
|
if (!databaseService.IsDatabaseValid())
|
||||||
{
|
{
|
||||||
await Task.Delay(5000, _appLifeTime.ApplicationStopping);
|
await Task.Delay(5000, appLifeTime.ApplicationStopping);
|
||||||
|
|
||||||
// Skip forward to the next loop
|
// Skip forward to the next loop
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var updateable in _onUpdateComponents)
|
foreach (var updateable in onUpdateComponents)
|
||||||
{
|
{
|
||||||
var updateableName = updateable.GetType().FullName;
|
var updateableName = updateable.GetType().FullName;
|
||||||
if (string.IsNullOrEmpty(updateableName))
|
if (string.IsNullOrEmpty(updateableName))
|
||||||
@@ -99,13 +96,13 @@ public class App(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lastRunTimeTimestamp = _onUpdateLastRun.GetValueOrDefault(updateableName, 0);
|
var lastRunTimeTimestamp = _onUpdateLastRun.GetValueOrDefault(updateableName, 0);
|
||||||
var secondsSinceLastRun = _timeUtil.GetTimeStamp() - lastRunTimeTimestamp;
|
var secondsSinceLastRun = timeUtil.GetTimeStamp() - lastRunTimeTimestamp;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (await updateable.OnUpdate(secondsSinceLastRun))
|
if (await updateable.OnUpdate(secondsSinceLastRun))
|
||||||
{
|
{
|
||||||
_onUpdateLastRun[updateableName] = _timeUtil.GetTimeStamp();
|
_onUpdateLastRun[updateableName] = timeUtil.GetTimeStamp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception err)
|
catch (Exception err)
|
||||||
@@ -114,13 +111,13 @@ public class App(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(5000, _appLifeTime.ApplicationStopping);
|
await Task.Delay(5000, appLifeTime.ApplicationStopping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void LogUpdateException(Exception err, IOnUpdate updateable)
|
protected void LogUpdateException(Exception err, IOnUpdate updateable)
|
||||||
{
|
{
|
||||||
_logger.Error(_serverLocalisationService.GetText("scheduled_event_failed_to_run", updateable.GetType().FullName));
|
logger.Error(serverLocalisationService.GetText("scheduled_event_failed_to_run", updateable.GetType().FullName));
|
||||||
_logger.Error(err.ToString());
|
logger.Error(err.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using SPTarkov.Server.Core.Utils.Json;
|
|||||||
namespace SPTarkov.Server.Core.Utils;
|
namespace SPTarkov.Server.Core.Utils;
|
||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil, JsonUtil _jsonUtil)
|
public class ImporterUtil(ISptLogger<ImporterUtil> logger, FileUtil fileUtil, JsonUtil jsonUtil)
|
||||||
{
|
{
|
||||||
private readonly FrozenSet<string> _directoriesToIgnore = ["./SPT_Data/database/locales/server"];
|
private readonly FrozenSet<string> _directoriesToIgnore = ["./SPT_Data/database/locales/server"];
|
||||||
private readonly FrozenSet<string> _filesToIgnore = ["bearsuits.json", "usecsuits.json", "archivedquests.json"];
|
private readonly FrozenSet<string> _filesToIgnore = ["bearsuits.json", "usecsuits.json", "archivedquests.json"];
|
||||||
@@ -46,15 +46,15 @@ public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil,
|
|||||||
var result = Activator.CreateInstance(loadedType);
|
var result = Activator.CreateInstance(loadedType);
|
||||||
|
|
||||||
// get all filepaths
|
// get all filepaths
|
||||||
var files = _fileUtil.GetFiles(filePath);
|
var files = fileUtil.GetFiles(filePath);
|
||||||
var directories = _fileUtil.GetDirectories(filePath);
|
var directories = fileUtil.GetDirectories(filePath);
|
||||||
|
|
||||||
// Process files
|
// Process files
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
_fileUtil.GetFileExtension(file) != "json"
|
fileUtil.GetFileExtension(file) != "json"
|
||||||
|| _filesToIgnore.Contains(_fileUtil.GetFileNameAndExtension(file).ToLowerInvariant())
|
|| _filesToIgnore.Contains(fileUtil.GetFileNameAndExtension(file).ToLowerInvariant())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -98,7 +98,7 @@ public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil,
|
|||||||
|
|
||||||
// Get the set method to update the object
|
// Get the set method to update the object
|
||||||
var setMethod = GetSetMethod(
|
var setMethod = GetSetMethod(
|
||||||
_fileUtil.StripExtension(file).ToLowerInvariant(),
|
fileUtil.StripExtension(file).ToLowerInvariant(),
|
||||||
loadedType,
|
loadedType,
|
||||||
out var propertyType,
|
out var propertyType,
|
||||||
out var isDictionary
|
out var isDictionary
|
||||||
@@ -113,7 +113,7 @@ public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil,
|
|||||||
|
|
||||||
lock (dictionaryLock)
|
lock (dictionaryLock)
|
||||||
{
|
{
|
||||||
setMethod.Invoke(result, isDictionary ? [_fileUtil.StripExtension(file), fileDeserialized] : [fileDeserialized]);
|
setMethod.Invoke(result, isDictionary ? [fileUtil.StripExtension(file), fileDeserialized] : [fileDeserialized]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -179,7 +179,7 @@ public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil,
|
|||||||
return CreateLazyLoadDeserialization(file, propertyType);
|
return CreateLazyLoadDeserialization(file, propertyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await _jsonUtil.DeserializeFromFileAsync(file, propertyType);
|
return await jsonUtil.DeserializeFromFileAsync(file, propertyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private object CreateLazyLoadDeserialization(string file, Type propertyType)
|
private object CreateLazyLoadDeserialization(string file, Type propertyType)
|
||||||
@@ -187,7 +187,7 @@ public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil,
|
|||||||
var genericArgument = propertyType.GetGenericArguments()[0];
|
var genericArgument = propertyType.GetGenericArguments()[0];
|
||||||
|
|
||||||
var deserializeCall = Expression.Call(
|
var deserializeCall = Expression.Call(
|
||||||
Expression.Constant(_jsonUtil),
|
Expression.Constant(jsonUtil),
|
||||||
"DeserializeFromFile",
|
"DeserializeFromFile",
|
||||||
Type.EmptyTypes,
|
Type.EmptyTypes,
|
||||||
Expression.Constant(file),
|
Expression.Constant(file),
|
||||||
@@ -220,14 +220,14 @@ public class ImporterUtil(ISptLogger<ImporterUtil> _logger, FileUtil _fileUtil,
|
|||||||
.FirstOrDefault(prop =>
|
.FirstOrDefault(prop =>
|
||||||
string.Equals(
|
string.Equals(
|
||||||
prop.Name.ToLowerInvariant(),
|
prop.Name.ToLowerInvariant(),
|
||||||
_fileUtil.StripExtension(propertyName).ToLowerInvariant(),
|
fileUtil.StripExtension(propertyName).ToLowerInvariant(),
|
||||||
StringComparison.Ordinal
|
StringComparison.Ordinal
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchedProperty == null)
|
if (matchedProperty == null)
|
||||||
{
|
{
|
||||||
throw new Exception($"Unable to find property '{_fileUtil.StripExtension(propertyName)}' for type '{type.Name}'");
|
throw new Exception($"Unable to find property '{fileUtil.StripExtension(propertyName)}' for type '{type.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
propertyType = matchedProperty.PropertyType;
|
propertyType = matchedProperty.PropertyType;
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ namespace SPTarkov.Server.Core.Utils;
|
|||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class RagfairOfferHolder(
|
public class RagfairOfferHolder(
|
||||||
ISptLogger<RagfairOfferHolder> _logger,
|
ISptLogger<RagfairOfferHolder> logger,
|
||||||
RagfairServerHelper _ragfairServerHelper,
|
RagfairServerHelper ragfairServerHelper,
|
||||||
ServerLocalisationService _serverLocalisationService,
|
ServerLocalisationService serverLocalisationService,
|
||||||
ItemHelper _itemHelper
|
ItemHelper itemHelper
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -146,7 +146,7 @@ public class RagfairOfferHolder(
|
|||||||
!itemTpl.IsEmpty // Has tpl
|
!itemTpl.IsEmpty // Has tpl
|
||||||
&& offer.IsFakePlayerOffer()
|
&& offer.IsFakePlayerOffer()
|
||||||
&& _fakePlayerOffers.TryGetValue(itemTpl, out var offers)
|
&& _fakePlayerOffers.TryGetValue(itemTpl, out var offers)
|
||||||
&& offers?.Count >= _ragfairServerHelper.GetOfferCountByBaseType(_itemHelper.GetItem(itemTpl).Value.Parent)
|
&& offers?.Count >= ragfairServerHelper.GetOfferCountByBaseType(itemHelper.GetItem(itemTpl).Value.Parent)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// If it is an NPC PMC offer AND we have already reached the maximum amount of possible offers
|
// If it is an NPC PMC offer AND we have already reached the maximum amount of possible offers
|
||||||
@@ -156,7 +156,7 @@ public class RagfairOfferHolder(
|
|||||||
|
|
||||||
if (!_offersById.TryAdd(offer.Id, offer))
|
if (!_offersById.TryAdd(offer.Id, offer))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Offer: {offer.Id} already exists");
|
logger.Warning($"Offer: {offer.Id} already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offer.IsTraderOffer())
|
if (offer.IsTraderOffer())
|
||||||
@@ -182,14 +182,14 @@ public class RagfairOfferHolder(
|
|||||||
{
|
{
|
||||||
if (!_offersById.TryGetValue(offerId, out var offer))
|
if (!_offersById.TryGetValue(offerId, out var offer))
|
||||||
{
|
{
|
||||||
_logger.Warning(_serverLocalisationService.GetText("ragfair-unable_to_remove_offer_doesnt_exist", offerId));
|
logger.Warning(serverLocalisationService.GetText("ragfair-unable_to_remove_offer_doesnt_exist", offerId));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_offersById.TryRemove(offer.Id, out _))
|
if (!_offersById.TryRemove(offer.Id, out _))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to remove offer by id: {offer.Id} not found");
|
logger.Warning($"Unable to remove offer by id: {offer.Id} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkTraderOffers && _offersByTrader.TryGetValue(offer.User.Id, out var traderOfferIds))
|
if (checkTraderOffers && _offersByTrader.TryGetValue(offer.User.Id, out var traderOfferIds))
|
||||||
@@ -202,7 +202,7 @@ public class RagfairOfferHolder(
|
|||||||
// Users with no offers were never cleaned up
|
// Users with no offers were never cleaned up
|
||||||
if (!_offersByTrader.TryRemove(offer.User.Id, out _))
|
if (!_offersByTrader.TryRemove(offer.User.Id, out _))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to remove Trader offer: {offer.Id} not found");
|
logger.Warning($"Unable to remove Trader offer: {offer.Id} not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,7 +235,7 @@ public class RagfairOfferHolder(
|
|||||||
{
|
{
|
||||||
if (!_offersById.TryRemove(offerId, out _))
|
if (!_offersById.TryRemove(offerId, out _))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to remove offer: {offerId}");
|
logger.Warning($"Unable to remove offer: {offerId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +265,7 @@ public class RagfairOfferHolder(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Warning($"Unable to add offer: {offerId} to _offersByTemplate");
|
logger.Warning($"Unable to add offer: {offerId} to _offersByTemplate");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ public class RagfairOfferHolder(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Error($"Unable to add offer: {offerId} to _offersByTrader");
|
logger.Error($"Unable to add offer: {offerId} to _offersByTrader");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ public class RagfairOfferHolder(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Error($"Unable to add offer: {offerId} to _fakePlayerOffers");
|
logger.Error($"Unable to add offer: {offerId} to _fakePlayerOffers");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -328,7 +328,7 @@ public class RagfairOfferHolder(
|
|||||||
{
|
{
|
||||||
if (!_expiredOfferIds.Add(staleOfferId))
|
if (!_expiredOfferIds.Add(staleOfferId))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to add offer: {staleOfferId} to expired offers");
|
logger.Warning($"Unable to add offer: {staleOfferId} to expired offers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,13 +364,13 @@ public class RagfairOfferHolder(
|
|||||||
var offer = GetOfferById(expiredOfferId);
|
var offer = GetOfferById(expiredOfferId);
|
||||||
if (offer is null)
|
if (offer is null)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Expired offerId: {expiredOfferId} not found, skipping");
|
logger.Warning($"Expired offerId: {expiredOfferId} not found, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offer.Items?.Count == 0)
|
if (offer.Items?.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.Error($"Expired offerId: {expiredOfferId} has no items, skipping");
|
logger.Error($"Expired offerId: {expiredOfferId} has no items, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,7 +401,7 @@ public class RagfairOfferHolder(
|
|||||||
{
|
{
|
||||||
foreach (var offer in GetOffers())
|
foreach (var offer in GetOffers())
|
||||||
{
|
{
|
||||||
if (_expiredOfferIds.Contains(offer.Id) || _ragfairServerHelper.IsTrader(offer.User.Id))
|
if (_expiredOfferIds.Contains(offer.Id) || ragfairServerHelper.IsTrader(offer.User.Id))
|
||||||
{
|
{
|
||||||
// Already flagged or trader offer (handled separately), skip
|
// Already flagged or trader offer (handled separately), skip
|
||||||
continue;
|
continue;
|
||||||
@@ -411,7 +411,7 @@ public class RagfairOfferHolder(
|
|||||||
{
|
{
|
||||||
if (!_expiredOfferIds.Add(offer.Id))
|
if (!_expiredOfferIds.Add(offer.Id))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to add offer: {offer.Id} to expired offers as it already exists");
|
logger.Warning($"Unable to add offer: {offer.Id} to expired offers as it already exists");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace SPTarkov.Server.Core.Utils;
|
|||||||
|
|
||||||
// TODO: Finish porting this class
|
// TODO: Finish porting this class
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class RandomUtil(ISptLogger<RandomUtil> _logger, ICloner _cloner)
|
public class RandomUtil(ISptLogger<RandomUtil> logger, ICloner cloner)
|
||||||
{
|
{
|
||||||
private const int DecimalPointRandomPrecision = 6;
|
private const int DecimalPointRandomPrecision = 6;
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ public class RandomUtil(ISptLogger<RandomUtil> _logger, ICloner _cloner)
|
|||||||
|
|
||||||
if (!replacement)
|
if (!replacement)
|
||||||
{
|
{
|
||||||
list = _cloner.Clone(originalList);
|
list = cloner.Clone(originalList);
|
||||||
// Adjust drawCount to avoid drawing more elements than available
|
// Adjust drawCount to avoid drawing more elements than available
|
||||||
if (drawCount > list.Count)
|
if (drawCount > list.Count)
|
||||||
{
|
{
|
||||||
@@ -324,13 +324,13 @@ public class RandomUtil(ISptLogger<RandomUtil> _logger, ICloner _cloner)
|
|||||||
|
|
||||||
if (max < min)
|
if (max < min)
|
||||||
{
|
{
|
||||||
_logger.Error($"Invalid argument, Bounded random number generation max is smaller than min({max} < {min}");
|
logger.Error($"Invalid argument, Bounded random number generation max is smaller than min({max} < {min}");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n < 1)
|
if (n < 1)
|
||||||
{
|
{
|
||||||
_logger.Error($"Invalid argument, 'n' must be 1 or greater(received {n})");
|
logger.Error($"Invalid argument, 'n' must be 1 or greater(received {n})");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,10 +346,10 @@ public class RandomUtil(ISptLogger<RandomUtil> _logger, ICloner _cloner)
|
|||||||
// A shift that is equal to the available range only has a 50% chance of rolling correctly, theoretically halving performance.
|
// A shift that is equal to the available range only has a 50% chance of rolling correctly, theoretically halving performance.
|
||||||
// Shifting even further drops the success chance very rapidly - so we want to warn against that
|
// Shifting even further drops the success chance very rapidly - so we want to warn against that
|
||||||
|
|
||||||
_logger.Warning(
|
logger.Warning(
|
||||||
"Bias shift for random number generation is greater than the range of available numbers. This will have a severe performance impact"
|
"Bias shift for random number generation is greater than the range of available numbers. This will have a severe performance impact"
|
||||||
);
|
);
|
||||||
_logger.Warning($"min-> {min}; max-> {max}; shift-> {shift}");
|
logger.Warning($"min-> {min}; max-> {max}; shift-> {shift}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var biasedMin = shift >= 0 ? min - shift : min;
|
var biasedMin = shift >= 0 ? min - shift : min;
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ using SPTarkov.Server.Core.Utils.Cloners;
|
|||||||
namespace UnitTests.Mock;
|
namespace UnitTests.Mock;
|
||||||
|
|
||||||
[Injectable(TypeOverride = typeof(RandomUtil))]
|
[Injectable(TypeOverride = typeof(RandomUtil))]
|
||||||
public class MockRandomUtil(ISptLogger<RandomUtil> _logger, ICloner _cloner) : RandomUtil(_logger, _cloner)
|
public class MockRandomUtil(ISptLogger<RandomUtil> logger, ICloner cloner) : RandomUtil(logger, cloner)
|
||||||
{
|
{
|
||||||
public override int GetInt(int min, int max = Int32.MaxValue, bool exclusive = false)
|
public override int GetInt(int min, int max = int.MaxValue, bool exclusive = false)
|
||||||
{
|
{
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ namespace HideoutCraftQuestIdGenerator;
|
|||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class HideoutCraftQuestIdGenerator(
|
public class HideoutCraftQuestIdGenerator(
|
||||||
ISptLogger<HideoutCraftQuestIdGenerator> _logger,
|
ISptLogger<HideoutCraftQuestIdGenerator> logger,
|
||||||
FileUtil _fileUtil,
|
FileUtil fileUtil,
|
||||||
JsonUtil _jsonUtil,
|
JsonUtil jsonUtil,
|
||||||
DatabaseServer _databaseServer,
|
DatabaseServer databaseServer,
|
||||||
ItemHelper _itemHelper,
|
ItemHelper itemHelper,
|
||||||
DatabaseImporter _databaseImporter
|
DatabaseImporter databaseImporter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
private static readonly HashSet<MongoId> _blacklistedProductions =
|
private static readonly HashSet<MongoId> _blacklistedProductions =
|
||||||
@@ -41,7 +41,7 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
|
|
||||||
public async Task Run()
|
public async Task Run()
|
||||||
{
|
{
|
||||||
await _databaseImporter.OnLoad();
|
await databaseImporter.OnLoad();
|
||||||
|
|
||||||
// Build up our dataset
|
// Build up our dataset
|
||||||
BuildQuestProductionList();
|
BuildQuestProductionList();
|
||||||
@@ -52,14 +52,14 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
const string productionPath = "Libraries\\SPTarkov.Server.Assets\\SPT_Data\\database\\hideout\\production.json";
|
const string productionPath = "Libraries\\SPTarkov.Server.Assets\\SPT_Data\\database\\hideout\\production.json";
|
||||||
var productionFilePath = Path.Combine(projectDir.FullName, productionPath);
|
var productionFilePath = Path.Combine(projectDir.FullName, productionPath);
|
||||||
|
|
||||||
var updatedProductionJson = _jsonUtil.Serialize(_databaseServer.GetTables().Hideout.Production, true);
|
var updatedProductionJson = jsonUtil.Serialize(databaseServer.GetTables().Hideout.Production, true);
|
||||||
await _fileUtil.WriteFileAsync(productionFilePath, updatedProductionJson);
|
await fileUtil.WriteFileAsync(productionFilePath, updatedProductionJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a list of all quests and what production they unlock
|
// Build a list of all quests and what production they unlock
|
||||||
private void BuildQuestProductionList()
|
private void BuildQuestProductionList()
|
||||||
{
|
{
|
||||||
foreach (var (questId, quest) in _databaseServer.GetTables().Templates.Quests)
|
foreach (var (questId, quest) in databaseServer.GetTables().Templates.Quests)
|
||||||
{
|
{
|
||||||
var combinedRewards = CombineRewards(quest.Rewards).Where(x => x.Type == RewardType.ProductionScheme).ToList();
|
var combinedRewards = CombineRewards(quest.Rewards).Where(x => x.Type == RewardType.ProductionScheme).ToList();
|
||||||
foreach (var reward in combinedRewards)
|
foreach (var reward in combinedRewards)
|
||||||
@@ -78,7 +78,7 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
{
|
{
|
||||||
if (item.Template != output.ItemTemplate)
|
if (item.Template != output.ItemTemplate)
|
||||||
{
|
{
|
||||||
_logger.Error($"Production scheme has multiple output items. " + $"{output.ItemTemplate} != {item.Template}");
|
logger.Error($"Production scheme has multiple output items. " + $"{output.ItemTemplate} != {item.Template}");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -94,12 +94,12 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
private void UpdateProductionQuests()
|
private void UpdateProductionQuests()
|
||||||
{
|
{
|
||||||
// Loop through all productions, and try to associate any with a `QuestComplete` type with its quest
|
// Loop through all productions, and try to associate any with a `QuestComplete` type with its quest
|
||||||
foreach (var production in _databaseServer.GetTables().Hideout.Production.Recipes)
|
foreach (var production in databaseServer.GetTables().Hideout.Production.Recipes)
|
||||||
{
|
{
|
||||||
// Skip blacklisted productions
|
// Skip blacklisted productions
|
||||||
if (_blacklistedProductions.Contains(production.Id))
|
if (_blacklistedProductions.Contains(production.Id))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Skipped blacklisted production: {production.Id}");
|
logger.Debug($"Skipped blacklisted production: {production.Id}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
|
|
||||||
if (questCompleteRequirements.Count > 1)
|
if (questCompleteRequirements.Count > 1)
|
||||||
{
|
{
|
||||||
_logger.Error($"Error, prodId: {production.Id} contains multiple QuestComplete requirements");
|
logger.Error($"Error, prodId: {production.Id} contains multiple QuestComplete requirements");
|
||||||
|
|
||||||
// Production has no multiple quest requirements
|
// Production has no multiple quest requirements
|
||||||
continue;
|
continue;
|
||||||
@@ -122,11 +122,11 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
// Check for forced ids
|
// Check for forced ids
|
||||||
if (_forcedQuestToProductionAssociations.TryGetValue(production.Id, out var associatedQuestIdToComplete))
|
if (_forcedQuestToProductionAssociations.TryGetValue(production.Id, out var associatedQuestIdToComplete))
|
||||||
{
|
{
|
||||||
var enLocale = _databaseServer.GetTables().Locales.Global["en"].Value;
|
var enLocale = databaseServer.GetTables().Locales.Global["en"].Value;
|
||||||
var questName = enLocale[$"{associatedQuestIdToComplete} name"];
|
var questName = enLocale[$"{associatedQuestIdToComplete} name"];
|
||||||
// Found one, move to next production
|
// Found one, move to next production
|
||||||
_logger.Success(
|
logger.Success(
|
||||||
$"FORCED - Updated: prodId: {production.Id} endProd: {production.EndProduct} ({_itemHelper.GetItemName(production.EndProduct)}) with quantity: {production.Count} to quest: {associatedQuestIdToComplete} {questName}"
|
$"FORCED - Updated: prodId: {production.Id} endProd: {production.EndProduct} ({itemHelper.GetItemName(production.EndProduct)}) with quantity: {production.Count} to quest: {associatedQuestIdToComplete} {questName}"
|
||||||
);
|
);
|
||||||
questCompleteRequirements[0].QuestId = associatedQuestIdToComplete;
|
questCompleteRequirements[0].QuestId = associatedQuestIdToComplete;
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
// Update the production quest ID
|
// Update the production quest ID
|
||||||
_questProductionMap[questProductionOutputs[0].QuestId] = production.Id;
|
_questProductionMap[questProductionOutputs[0].QuestId] = production.Id;
|
||||||
questCompleteRequirements[0].QuestId = questProductionOutputs[0].QuestId;
|
questCompleteRequirements[0].QuestId = questProductionOutputs[0].QuestId;
|
||||||
_logger.Success(
|
logger.Success(
|
||||||
$"Updated prodId: {production.Id}, endProd: {production.EndProduct} quantity: {production.Count} to quest: {questProductionOutputs[0].QuestId} {questProductionOutputs[0].QuestName}"
|
$"Updated prodId: {production.Id}, endProd: {production.EndProduct} quantity: {production.Count} to quest: {questProductionOutputs[0].QuestId} {questProductionOutputs[0].QuestName}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -162,8 +162,8 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
// A lot of error handling for edge cases
|
// A lot of error handling for edge cases
|
||||||
if (!questProductionOutputs.Any())
|
if (!questProductionOutputs.Any())
|
||||||
{
|
{
|
||||||
_logger.Error(
|
logger.Error(
|
||||||
$"Error: Unable to find matching quest for prodId: {production.Id}, endProduct: {production.EndProduct} ({_itemHelper.GetItemName(production.EndProduct)}) quantity: {production.Count}. Potential new or removed quest?"
|
$"Error: Unable to find matching quest for prodId: {production.Id}, endProduct: {production.EndProduct} ({itemHelper.GetItemName(production.EndProduct)}) quantity: {production.Count}. Potential new or removed quest?"
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
if (questProductionOutputs.Count > 1)
|
if (questProductionOutputs.Count > 1)
|
||||||
{
|
{
|
||||||
var questNamesCSV = string.Join(",", questProductionOutputs.Select(x => x.QuestName));
|
var questNamesCSV = string.Join(",", questProductionOutputs.Select(x => x.QuestName));
|
||||||
_logger.Error(
|
logger.Error(
|
||||||
$"Error: Multiple quests match prodId: {production.Id}, endProduct: {production.EndProduct} with quantity: {production.Count}, quests: {questNamesCSV}"
|
$"Error: Multiple quests match prodId: {production.Id}, endProduct: {production.EndProduct} with quantity: {production.Count}, quests: {questNamesCSV}"
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@@ -179,7 +179,7 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
|
|
||||||
if (questComplete.QuestId is not null && questComplete.QuestId != questProductionOutputs[0].QuestId)
|
if (questComplete.QuestId is not null && questComplete.QuestId != questProductionOutputs[0].QuestId)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
logger.Error(
|
||||||
$"Error: Multiple productions match quest. EndProduct: {production.EndProduct} with quantity {production.Count}, existing quest: {questComplete.QuestId} {questProductionOutputs[0].QuestName}"
|
$"Error: Multiple productions match quest. EndProduct: {production.EndProduct} with quantity {production.Count}, existing quest: {questComplete.QuestId} {questProductionOutputs[0].QuestName}"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -188,11 +188,11 @@ public class HideoutCraftQuestIdGenerator(
|
|||||||
|
|
||||||
if (_questProductionMap.ContainsKey(questProductionOutputs[0].QuestId))
|
if (_questProductionMap.ContainsKey(questProductionOutputs[0].QuestId))
|
||||||
{
|
{
|
||||||
var recipies = _databaseServer.GetTables().Hideout.Production.Recipes;
|
var recipies = databaseServer.GetTables().Hideout.Production.Recipes;
|
||||||
var prodId = _questProductionMap[questProductionOutputs[0].QuestId];
|
var prodId = _questProductionMap[questProductionOutputs[0].QuestId];
|
||||||
var prod = recipies.FirstOrDefault(x => x.Id == prodId);
|
var prod = recipies.FirstOrDefault(x => x.Id == prodId);
|
||||||
var prodItemName = _itemHelper.GetItemName(prod.EndProduct);
|
var prodItemName = itemHelper.GetItemName(prod.EndProduct);
|
||||||
_logger.Warning(
|
logger.Warning(
|
||||||
$"Error: Quest {questProductionOutputs[0].QuestId} {questProductionOutputs[0].QuestName} already associated with production: {prodId} {prodItemName}. Potential conflict"
|
$"Error: Quest {questProductionOutputs[0].QuestId} {questProductionOutputs[0].QuestName} already associated with production: {prodId} {prodItemName}. Potential conflict"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user