LazyLoad some assets

This commit is contained in:
clodan
2025-01-21 15:56:17 +00:00
parent 31f2d9f8dc
commit e2566d57f4
9 changed files with 95 additions and 21 deletions
+2 -2
View File
@@ -171,8 +171,8 @@ public class DataCallbacks(
{
var localeId = url.Replace("/client/locale/", "");
var locales = _databaseService.GetLocales();
var result = locales.Global?[localeId]
?? locales.Global?.FirstOrDefault(m => m.Key == "en").Value;
var result = locales.Global?[localeId].Value
?? locales.Global?.FirstOrDefault(m => m.Key == "en").Value.Value;
return _httpResponseUtil.GetUnclearedBody(result);
}
+4 -3
View File
@@ -1,5 +1,6 @@
using System.Text.Json.Serialization;
using Core.Models.Eft.Common.Tables;
using Core.Utils.Json;
namespace Core.Models.Eft.Common;
@@ -11,15 +12,15 @@ public record Location
/** Loose loot positions and item weights */
[JsonPropertyName("looseLoot")]
public LooseLoot? LooseLoot { get; set; }
public LazyLoad<LooseLoot>? LooseLoot { get; set; }
/** Static loot item weights */
[JsonPropertyName("staticLoot")]
public Dictionary<string, StaticLootDetails>? StaticLoot { get; set; }
public LazyLoad<Dictionary<string, StaticLootDetails>>? StaticLoot { get; set; }
/** Static container positions and item weights */
[JsonPropertyName("staticContainers")]
public StaticContainerDetails? StaticContainers { get; set; }
public LazyLoad<StaticContainerDetails>? StaticContainers { get; set; }
[JsonPropertyName("staticAmmo")]
public Dictionary<string, List<StaticAmmoDetails>> StaticAmmo { get; set; }
@@ -1,18 +1,16 @@
using System.Text.Json.Serialization;
using Core.Utils.Json;
namespace Core.Models.Spt.Server;
public record LocaleBase
{
[JsonPropertyName("global")]
public Dictionary<string, Dictionary<string, string>>? Global { get; set; }
public Dictionary<string, LazyLoad<Dictionary<string, string>>>? Global { get; set; }
[JsonPropertyName("menu")]
public Dictionary<string, Dictionary<string, object>>? Menu { get; set; }
[JsonPropertyName("languages")]
public Dictionary<string, string>? Languages { get; set; }
[JsonPropertyName("server")]
public Dictionary<string, Dictionary<string, string>>? Server { get; set; }
}
+8 -5
View File
@@ -1,4 +1,5 @@
using Core.Utils;
using Core.Utils.Json;
using SptCommon.Extensions;
namespace Core.Services;
@@ -13,7 +14,7 @@ public class I18nService
private FileUtil _fileUtil;
private string _setLocale;
private Dictionary<string, Dictionary<string, string>> _loadedLocales = new();
private Dictionary<string, LazyLoad<Dictionary<string, string>>> _loadedLocales = new();
// TODO: try convert to primary ctor
public I18nService(
FileUtil fileUtil,
@@ -41,8 +42,10 @@ public class I18nService
throw new Exception($"Localisation files in directory {_directory} not found.");
foreach (var file in files)
_loadedLocales.Add(_fileUtil.StripExtension(file),
_jsonUtil.Deserialize<Dictionary<string, string>>(_fileUtil.ReadFile(file)) ??
new Dictionary<string, string>());
new LazyLoad<Dictionary<string, string>>(
() => _jsonUtil.Deserialize<Dictionary<string, string>>(_fileUtil.ReadFile(file)) ??
new Dictionary<string, string>()
));
if (!_loadedLocales.ContainsKey(_defaultLocale))
throw new Exception($"The default locale '{_defaultLocale}' does not exist on the loaded locales.");
@@ -74,10 +77,10 @@ public class I18nService
{
if (!_loadedLocales.TryGetValue(_setLocale, out var locales))
return key;
if (!locales.TryGetValue(key, out var value))
if (!locales.Value.TryGetValue(key, out var value))
{
_loadedLocales.TryGetValue(_defaultLocale, out var defaults);
defaults.TryGetValue(key, out value);
defaults.Value.TryGetValue(key, out value);
return value ?? key;
}
+2 -2
View File
@@ -25,13 +25,13 @@ public class LocaleService(
public Dictionary<string, string> GetLocaleDb()
{
var desiredLocale = _databaseServer.GetTables().Locales.Global[GetDesiredGameLocale()];
if (desiredLocale != null) return desiredLocale;
if (desiredLocale != null) return desiredLocale.Value;
_logger.Warning(
$"Unable to find desired locale file using locale: {GetDesiredGameLocale()} from config/locale.json, falling back to 'en'"
);
return _databaseServer.GetTables().Locales.Global["en"];
return _databaseServer.GetTables().Locales.Global["en"].Value;
}
/**
@@ -330,7 +330,7 @@ public class LocationLifecycleService
locationBaseClone.Loot.AddRange(staticLoot);
// Add dynamic loot to output loot
var dynamicLootDistClone = _cloner.Clone(location.LooseLoot);
var dynamicLootDistClone = _cloner.Clone(location.LooseLoot.Value);
var dynamicSpawnPoints = _locationLootGenerator.GenerateDynamicLoot(
dynamicLootDistClone,
staticAmmoDist,
@@ -763,8 +763,8 @@ public class SeasonalEventService(
protected void RenameBitcoin()
{
var enLocale = _databaseService.GetLocales().Global["en"];
enLocale[$"{ItemTpl.BARTER_PHYSICAL_BITCOIN} Name"] = "Physical SPT Coin";
enLocale[$"{ItemTpl.BARTER_PHYSICAL_BITCOIN} ShortName"] = "0.2SPT";
enLocale.Value[$"{ItemTpl.BARTER_PHYSICAL_BITCOIN} Name"] = "Physical SPT Coin";
enLocale.Value[$"{ItemTpl.BARTER_PHYSICAL_BITCOIN} ShortName"] = "0.2SPT";
}
/// <summary>
+40 -2
View File
@@ -1,6 +1,8 @@
using System.Linq.Expressions;
using System.Reflection;
using SptCommon.Annotations;
using Core.Models.Utils;
using Core.Utils.Json;
namespace Core.Utils;
@@ -12,6 +14,7 @@ public class ImporterUtil
protected ISptLogger<ImporterUtil> _logger;
protected HashSet<string> filesToIgnore = ["bearsuits.json", "usecsuits.json", "archivedquests.json"];
protected HashSet<string> directoriesToIgnore = ["./Assets/database/locales/server"];
public ImporterUtil(ISptLogger<ImporterUtil> logger, FileUtil fileUtil, JsonUtil jsonUtil)
{
@@ -26,7 +29,8 @@ public class ImporterUtil
Action<string, object>? onObjectDeserialized = null
)
{
return LoadRecursiveAsync(filepath, typeof(T), onReadCallback, onObjectDeserialized).ContinueWith(res => (T) res.Result);
return LoadRecursiveAsync(filepath, typeof(T), onReadCallback, onObjectDeserialized)
.ContinueWith(res => (T)res.Result);
}
/**
@@ -70,7 +74,40 @@ public class ImporterUtil
);
try
{
var fileDeserialized = _jsonUtil.Deserialize(fileData, propertyType);
object fileDeserialized = null;
if (propertyType.IsGenericType &&
propertyType.GetGenericTypeDefinition() == typeof(LazyLoad<>))
{
// This expression is create a generic type delegate for lazy loading a LazyLoad type
var expression = Expression.Lambda(
// this is the expected type of the lambda which is a function of whatever generic type LazyLoad<> is
typeof(Func<>).MakeGenericType(propertyType.GetGenericArguments()),
// An expression block will have a return type and then will execute the expression
Expression.Block(
// this is the return type
propertyType.GetGenericArguments()[0],
// this is the expression
// This expression casts the result of the Call expression as the generic argument type
Expression.TypeAs(
// this expression calls the json util Deserialize method
Expression.Call(
Expression.Constant(_jsonUtil),
"Deserialize",
[],
[Expression.Constant(fileData), Expression.Constant(propertyType.GetGenericArguments()[0])]
),
propertyType.GetGenericArguments()[0]
)
)
)
.Compile();
fileDeserialized = Activator.CreateInstance(propertyType, expression);
}
else
{
fileDeserialized = _jsonUtil.Deserialize(fileData, propertyType);
}
if (onObjectDeserialized != null)
onObjectDeserialized(file, fileDeserialized);
@@ -96,6 +133,7 @@ public class ImporterUtil
// deep tree search
foreach (var directory in directories)
{
if (directoriesToIgnore.Contains(directory)) continue;
tasks.Add(
Task.Factory.StartNew(
() =>
+34
View File
@@ -0,0 +1,34 @@
namespace Core.Utils.Json;
public class LazyLoad<T>(Func<T> deserialize)
{
private T? _result;
private bool _isLoaded;
private Timer? autoCleanerTimeout;
private static readonly TimeSpan _autoCleanerTimeout = TimeSpan.FromSeconds(30);
public T? Value
{
get
{
if (!_isLoaded)
{
_result = deserialize();
_isLoaded = true;
autoCleanerTimeout = new Timer(_ =>
{
_result = default;
_isLoaded = false;
autoCleanerTimeout?.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
autoCleanerTimeout = null;
},null, _autoCleanerTimeout, Timeout.InfiniteTimeSpan
);
}
autoCleanerTimeout?.Change(_autoCleanerTimeout, Timeout.InfiniteTimeSpan);
return _result;
}
set => _result = value;
}
}