v1.7.7.0 (Winter Update 2024)

This commit is contained in:
Regalis11
2024-12-11 13:26:13 +02:00
parent 7d5b7a310a
commit f6349b2175
256 changed files with 4794 additions and 1653 deletions
@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using Barotrauma.IO;
using Barotrauma.Extensions;
@@ -87,13 +87,34 @@ namespace Barotrauma
))
}.ToImmutableDictionary();
private readonly struct CachedCategory
{
public readonly SpeciallyHandledCharCategory Category;
public readonly double LastAccessed;
public CachedCategory(SpeciallyHandledCharCategory category)
{
Category = category;
LastAccessed = Timing.TotalTime;
}
}
const int SpeciallyHandledCategoriesCacheSize = 5000;
private static readonly Dictionary<string, CachedCategory> SpeciallyHandledCategoriesCache = new Dictionary<string, CachedCategory>();
public static SpeciallyHandledCharCategory GetSpeciallyHandledCategories(LocalizedString text)
=> GetSpeciallyHandledCategories(text.Value);
public static SpeciallyHandledCharCategory GetSpeciallyHandledCategories(string text)
{
if (string.IsNullOrEmpty(text)) { return SpeciallyHandledCharCategory.None; }
if (SpeciallyHandledCategoriesCache.TryGetValue(text, out var cachedCategory))
{
SpeciallyHandledCategoriesCache[text] = new CachedCategory(cachedCategory.Category);
return cachedCategory.Category;
}
var retVal = SpeciallyHandledCharCategory.None;
for (int i = 0; i < text.Length; i++)
{
@@ -101,7 +122,7 @@ namespace Barotrauma
foreach (var category in SpeciallyHandledCharCategories)
{
if (retVal.HasFlag(category)) { continue; }
if (retVal.AlreadyHasCategoryFlag(category)) { continue; }
for (int j = 0; j < SpeciallyHandledCharacterRanges[category].Length; j++)
{
@@ -126,17 +147,42 @@ namespace Barotrauma
// Input contains characters from all
// specially handled categories, there's
// no need to inspect the string further
return SpeciallyHandledCharCategory.All;
break;
}
}
SpeciallyHandledCategoriesCache[text] = new CachedCategory(retVal);
TrimSpeciallyHandledCategoriesCache();
return retVal;
}
private static void TrimSpeciallyHandledCategoriesCache()
{
if (SpeciallyHandledCategoriesCache.Count > SpeciallyHandledCategoriesCacheSize)
{
//drop half of the cache, starting from the strings that haven't been used in the longest time
//this is relatively expensive (instantiates a big new list),
//but the cache should get cleared so infrequently (when 5000 unique texts have been visible, which may not even happen in normal gameplay)
//it should not have much effect in practice
foreach (var cachedVal in SpeciallyHandledCategoriesCache.OrderBy(static c => c.Value.LastAccessed).Take(SpeciallyHandledCategoriesCacheSize / 2).ToList())
{
SpeciallyHandledCategoriesCache.Remove(cachedVal.Key);
}
}
}
public static bool IsCJK(LocalizedString text)
=> IsCJK(text.Value);
public static bool IsCJK(string text)
=> GetSpeciallyHandledCategories(text).HasFlag(SpeciallyHandledCharCategory.CJK);
=> GetSpeciallyHandledCategories(text).AlreadyHasCategoryFlag(SpeciallyHandledCharCategory.CJK);
// This is a local optimized version of HasFlag/HasAnyFlag, which makes sense here because the loop using this is big enough
// to have made 8GB worth of memory allocations with HasFlag and still several dozen MB with the generic HasAnyFlag.
private static bool AlreadyHasCategoryFlag(this SpeciallyHandledCharCategory existingFlags, SpeciallyHandledCharCategory categoryFlag)
{
return (existingFlags & categoryFlag) != 0;
}
/// <summary>
/// Check if the currently selected language is available, and switch to English if not