Files
SPT-Server-Build/Libraries/Core/Services/BotNameService.cs
T
2025-02-05 07:36:13 +00:00

149 lines
5.1 KiB
C#

using SptCommon.Annotations;
using Core.Models.Eft.Common.Tables;
using Core.Models.Spt.Bots;
using Core.Helpers;
using Core.Models.Spt.Config;
using Core.Models.Utils;
using Core.Servers;
using Core.Utils;
using LogLevel = Core.Models.Spt.Logging.LogLevel;
namespace Core.Services;
[Injectable(InjectionType.Singleton)]
public class BotNameService(
ISptLogger<BotNameService> _logger,
BotHelper _botHelper,
RandomUtil _randomUtil,
LocalisationService _localisationService,
DatabaseService _databaseService,
ConfigServer _configServer
)
{
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
protected HashSet<string> _usedNameCache = new();
protected object _lock = new();
/// <summary>
/// Clear out any entries in Name Set
/// </summary>
public void ClearNameCache()
{
_usedNameCache.Clear();
}
/// <summary>
/// Create a unique bot nickname
/// </summary>
/// <param name="botJsonTemplate">bot JSON data from db</param>
/// <param name="botGenerationDetails"></param>
/// <param name="botRole">role of bot e.g. assault</param>
/// <param name="uniqueRoles">Lowercase roles to always make unique</param>
/// <returns>Nickname for bot</returns>
public string GenerateUniqueBotNickname(
BotType botJsonTemplate,
BotGenerationDetails botGenerationDetails,
string botRole,
List<string>? uniqueRoles = null)
{
var isPmc = botGenerationDetails.IsPmc;
// Never show for players
var showTypeInNickname = !botGenerationDetails.IsPlayerScav.GetValueOrDefault(false) && _botConfig.ShowTypeInNickname;
var roleShouldBeUnique = uniqueRoles?.Contains(botRole.ToLower());
var attempts = 0;
while (attempts <= 5)
{
// Get bot name with leading/trailing whitespace removed
var name = isPmc.GetValueOrDefault(false) // Explicit handling of PMCs, all other bots will get "first_name last_name"
? _botHelper.GetPmcNicknameOfMaxLength(_botConfig.BotNameLengthLimit, botGenerationDetails.Side)
: $"{_randomUtil.GetArrayValue(botJsonTemplate.FirstNames)} {(botJsonTemplate.LastNames.Count > 0 ? _randomUtil.GetArrayValue(botJsonTemplate.LastNames) : "")}";
name = name.Trim();
// Config is set to add role to end of bot name
if (showTypeInNickname) name += $" {botRole}";
// Replace pmc bot names with player name + prefix
if (botGenerationDetails.IsPmc.GetValueOrDefault(false) && botGenerationDetails.AllPmcsHaveSameNameAsPlayer.GetValueOrDefault(false))
{
var prefix = _localisationService.GetRandomTextThatMatchesPartialKey("pmc-name_prefix_");
name = $"{prefix} {name}";
}
// Is this a role that must be unique
if (roleShouldBeUnique.GetValueOrDefault(false))
// Check name in cache
if (CacheContainsName(name))
{
// Not unique
if (attempts >= 5)
{
// 5 attempts to generate a name, pool probably isn't big enough
var genericName = $"{botGenerationDetails.Side} {_randomUtil.GetInt(100000, 999999)}";
if (_logger.IsLogEnabled(LogLevel.Debug))
_logger.Debug($"Failed to find unique name for: {botRole} {botGenerationDetails.Side} after 5 attempts, using: {genericName}");
return genericName;
}
attempts++;
// Try again
continue;
}
// Add bot name to cache to prevent being used again
AddNameToCache(name);
return name;
}
// Should never reach here
return $"BOT {botRole} {botGenerationDetails.BotDifficulty}";
}
private bool AddNameToCache(string name)
{
lock (_lock)
{
return _usedNameCache.Add(name);
}
}
protected bool CacheContainsName(string name)
{
lock (_lock)
{
return _usedNameCache.Contains(name);
}
}
/// <summary>
/// Add random PMC name to bots MainProfileNickname property
/// </summary>
/// <param name="bot">Bot to update</param>
public void AddRandomPmcNameToBotMainProfileNicknameProperty(BotBase bot)
{
// Simulate bot looking like a player scav with the PMC name in brackets.
// E.g. "ScavName (PMC Name)"
bot.Info.MainProfileNickname = GetRandomPmcName();
}
/// <summary>
/// Choose a random PMC name from bear or usec bot jsons
/// </summary>
/// <returns>PMC name as string</returns>
protected string GetRandomPmcName()
{
var bots = _databaseService.GetBots().Types;
var pmcNames = new List<string>();
pmcNames.AddRange(bots["usec"].FirstNames);
pmcNames.AddRange(bots["bear"].FirstNames);
return _randomUtil.GetArrayValue(pmcNames);
}
}