This commit is contained in:
CWX
2025-01-08 21:09:44 +00:00
3 changed files with 98 additions and 67 deletions
+27 -23
View File
@@ -1,6 +1,7 @@
using System.Text.Json.Serialization;
using Core.Models.Enums;
using Core.Models.Spt.Services;
using Core.Utils.Json.Converters;
namespace Core.Models.Eft.Common.Tables;
@@ -64,7 +65,7 @@ public class TraderBase
public decimal? DiscountEnd { get; set; }
[JsonPropertyName("gridHeight")]
public int? GridHeight { get; set; }
public double? GridHeight { get; set; }
[JsonPropertyName("sell_modifier_for_prohibited_items")]
public decimal? SellModifierForProhibitedItems { get; set; }
@@ -100,7 +101,7 @@ public class TraderBase
public string? Name { get; set; }
[JsonPropertyName("nextResupply")]
public int? NextResupply { get; set; }
public double? NextResupply { get; set; }
[JsonPropertyName("nickname")]
public string? Nickname { get; set; }
@@ -136,43 +137,44 @@ public class TraderInsurance
public List<string>? ExcludedCategory { get; set; }
[JsonPropertyName("max_return_hour")]
public int? MaxReturnHour { get; set; }
public double? MaxReturnHour { get; set; }
[JsonPropertyName("max_storage_time")]
public int? MaxStorageTime { get; set; }
public double? MaxStorageTime { get; set; }
[JsonPropertyName("min_payment")]
public int? MinPayment { get; set; }
public double? MinPayment { get; set; }
[JsonPropertyName("min_return_hour")]
public int? MinReturnHour { get; set; }
public double? MinReturnHour { get; set; }
}
public class TraderLoyaltyLevel
{
[JsonPropertyName("buy_price_coef")]
public int? BuyPriceCoefficient { get; set; }
public double? BuyPriceCoefficient { get; set; }
[JsonPropertyName("exchange_price_coef")]
public int? ExchangePriceCoefficient { get; set; }
public double? ExchangePriceCoefficient { get; set; }
[JsonPropertyName("heal_price_coef")]
public int? HealPriceCoefficient { get; set; }
public double? HealPriceCoefficient { get; set; }
[JsonPropertyName("insurance_price_coef")]
public int? InsurancePriceCoefficient { get; set; }
[JsonConverter(typeof(StringToNumberFactoryConverter))]
public double? InsurancePriceCoefficient { get; set; }
[JsonPropertyName("minLevel")]
public int? MinLevel { get; set; }
public double? MinLevel { get; set; }
[JsonPropertyName("minSalesSum")]
public int? MinSalesSum { get; set; }
public double? MinSalesSum { get; set; }
[JsonPropertyName("minStanding")]
public int? MinStanding { get; set; }
public double? MinStanding { get; set; }
[JsonPropertyName("repair_price_coef")]
public int? RepairPriceCoefficient { get; set; }
public double? RepairPriceCoefficient { get; set; }
}
public class TraderRepair
@@ -193,13 +195,14 @@ public class TraderRepair
public List<string>? ExcludedIdList { get; set; } // Doesn't exist in client object
[JsonPropertyName("quality")]
public int? Quality { get; set; }
[JsonConverter(typeof(StringToNumberFactoryConverter))]
public double? Quality { get; set; }
}
public class TraderAssort
{
[JsonPropertyName("nextResupply")]
public int? NextResupply { get; set; }
public double? NextResupply { get; set; }
[JsonPropertyName("items")]
public List<Item>? Items { get; set; }
@@ -214,7 +217,7 @@ public class TraderAssort
public class BarterScheme
{
[JsonPropertyName("count")]
public int? Count { get; set; }
public double? Count { get; set; }
[JsonPropertyName("_tpl")]
public string? Template { get; set; }
@@ -226,9 +229,10 @@ public class BarterScheme
public bool? SptQuestLocked { get; set; }
[JsonPropertyName("level")]
public int? Level { get; set; }
public double? Level { get; set; }
[JsonPropertyName("side")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public DogtagExchangeSide? Side { get; set; }
}
@@ -265,13 +269,13 @@ public class SuitRequirements
public List<string>? AchievementRequirements { get; set; }
[JsonPropertyName("loyaltyLevel")]
public int? LoyaltyLevel { get; set; }
public double? LoyaltyLevel { get; set; }
[JsonPropertyName("profileLevel")]
public int? ProfileLevel { get; set; }
public double? ProfileLevel { get; set; }
[JsonPropertyName("standing")]
public int? Standing { get; set; }
public double? Standing { get; set; }
[JsonPropertyName("skillRequirements")]
public List<string>? SkillRequirements { get; set; }
@@ -289,7 +293,7 @@ public class SuitRequirements
public class ItemRequirement
{
[JsonPropertyName("count")]
public int? Count { get; set; }
public double? Count { get; set; }
[JsonPropertyName("_tpl")]
public string? Tpl { get; set; }
@@ -302,4 +306,4 @@ public class ItemRequirement
[JsonPropertyName("type")]
public string? Type { get; set; }
}
}
+70 -44
View File
@@ -21,13 +21,14 @@ public class ImporterUtil
* @param filepath Path to folder with files
* @returns Promise<T> return T type associated with this class
*/
public async Task<object> LoadRecursiveAsync(
public Task<object> LoadRecursiveAsync(
string filepath,
Type loadedType,
Action<string, string>? onReadCallback = null,
Action<string, object>? onObjectDeserialized = null
)
{
var tasks = new List<Task>();
var result = Activator.CreateInstance(loadedType);
// get all filepaths
@@ -40,58 +41,83 @@ public class ImporterUtil
if (_fileUtil.GetFileExtension(file) != "json") continue;
// to skip ArchivedQuests.json
if (file.ToLower().Contains("archived")) continue;
// const filename = this.vfs.stripExtension(file);
// const filePathAndName = `${filepath}${file}`;
var fileData = await File.ReadAllTextAsync(file);
if (onReadCallback != null)
onReadCallback(file, fileData);
tasks.Add(
Task.Factory.StartNew(() =>
{
// const filename = this.vfs.stripExtension(file);
// const filePathAndName = `${filepath}${file}`;
var fileData = File.ReadAllText(file);
if (onReadCallback != null)
onReadCallback(file, fileData);
Type propertyType;
MethodInfo setMethod;
var isDictionary = false;
if (loadedType.IsGenericType && loadedType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
propertyType = loadedType.GetGenericArguments()[1];
setMethod = loadedType.GetMethod("Add");
isDictionary = true;
}
else
{
var matchedProperty = loadedType.GetProperties()
.FirstOrDefault(prop => prop.Name.ToLower() == Path.GetFileNameWithoutExtension(file).ToLower());
if (matchedProperty == null)
throw new Exception($"Unable to find property '{Path.GetFileNameWithoutExtension(file)}' for type '{loadedType.Name}'");
propertyType = matchedProperty.PropertyType;
setMethod = matchedProperty.GetSetMethod();
}
var setMethod = GetSetMethod(
Path.GetFileNameWithoutExtension(file).ToLower(),
loadedType,
out var propertyType,
out var isDictionary
);
try
{
var fileDeserialized = JsonSerializer.Deserialize(fileData, propertyType,
new JsonSerializerOptions { UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow });
if (onObjectDeserialized != null)
onObjectDeserialized(file, fileDeserialized);
try
{
var fileDeserialized = JsonSerializer.Deserialize(fileData, propertyType,
new JsonSerializerOptions { UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow });
if (onObjectDeserialized != null)
onObjectDeserialized(file, fileDeserialized);
setMethod.Invoke(result, isDictionary ? [Path.GetFileNameWithoutExtension(file), fileDeserialized] : [fileDeserialized]);
}
catch (Exception e)
{
throw new Exception($"Unable to deserialize or set properties for file '{file}'", e);
}
setMethod.Invoke(result,
isDictionary ? [Path.GetFileNameWithoutExtension(file), fileDeserialized] : [fileDeserialized]);
}
catch (Exception e)
{
throw new Exception($"Unable to deserialize or set properties for file '{file}'", e);
}
})
);
}
// deep tree search
foreach (var directory in directories)
{
var matchedProperty = loadedType.GetProperties()
.FirstOrDefault(prop => prop.Name.ToLower() == directory.Split("/").Last().Replace("_", "").ToLower());
if (matchedProperty == null)
throw new Exception($"Unable to find property '{directory}' for type '{loadedType.Name}'");
matchedProperty.GetSetMethod().Invoke(result, [await LoadRecursiveAsync($"{directory}/", matchedProperty.PropertyType)]);
tasks.Add(
Task.Factory.StartNew(() =>
{
var setMethod = GetSetMethod(directory.Split("/").Last().Replace("_", ""), loadedType, out var matchedProperty, out var isDictionary);
var loadTask = LoadRecursiveAsync($"{directory}/", matchedProperty);
loadTask.Wait();
setMethod.Invoke(result, isDictionary ? [directory, loadTask.Result] : [loadTask.Result]);
})
);
}
// return the result of all async fetch
return result;
return Task.WhenAll(tasks).ContinueWith((t) =>
{
if (t.IsCanceled || t.IsFaulted)
tasks.Where(t => t.IsFaulted || t.IsCanceled).ToList().ForEach(t => Console.WriteLine(t.Exception));
}).ContinueWith(_ => result);
}
public MethodInfo GetSetMethod(string propertyName, Type type, out Type propertyType, out bool isDictionary)
{
MethodInfo setMethod;
isDictionary = false;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
propertyType = type.GetGenericArguments()[1];
setMethod = type.GetMethod("Add");
isDictionary = true;
}
else
{
var matchedProperty = type.GetProperties()
.FirstOrDefault(prop =>
prop.Name.ToLower() == Path.GetFileNameWithoutExtension(propertyName).ToLower());
if (matchedProperty == null)
throw new Exception(
$"Unable to find property '{Path.GetFileNameWithoutExtension(propertyName)}' for type '{type.Name}'");
propertyType = matchedProperty.PropertyType;
setMethod = matchedProperty.GetSetMethod();
}
return setMethod;
}
/**
@@ -204,4 +230,4 @@ public class ImporterUtil
}
}
}*/
}
}
+1
View File
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
<EnableDefaultContentItems>false</EnableDefaultContentItems>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>