mirror of
https://github.com/wangdage12/Snap.Hutao.git
synced 2026-07-31 04:10:25 +08:00
升级材料合并支持元素石
This commit is contained in:
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
|
using Snap.Hutao.Model.Metadata;
|
||||||
|
using Snap.Hutao.Model.Primitive;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Metadata;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Combine 元数据中多条配方可共享同一产物 Id(例如元素断片既有 3×碎屑合成,也有用其他元素石与尘的转化)。
|
||||||
|
/// 构建 MaterialId→Combine 映射时必须优先保留「单材料×3→产物×1」的合成台主链,否则后项覆盖前项会导致养成统计无法向下展开原料。
|
||||||
|
/// </summary>
|
||||||
|
internal static class CombineResultMaterialIdMapFactory
|
||||||
|
{
|
||||||
|
public static ImmutableDictionary<MaterialId, Combine> ToImmutableDictionary(ImmutableArray<Combine> combines)
|
||||||
|
{
|
||||||
|
Dictionary<MaterialId, Combine> map = [];
|
||||||
|
|
||||||
|
foreach (Combine current in combines)
|
||||||
|
{
|
||||||
|
MaterialId key = current.Result.Id;
|
||||||
|
if (!map.TryGetValue(key, out Combine? existing))
|
||||||
|
{
|
||||||
|
map[key] = current;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ComparePreference(current, existing) > 0)
|
||||||
|
{
|
||||||
|
map[key] = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map.ToImmutableDictionary();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>正数表示 <paramref name="incoming"/> 应取代已有项。</summary>
|
||||||
|
private static int ComparePreference(Combine incoming, Combine existing)
|
||||||
|
{
|
||||||
|
return Score(incoming).CompareTo(Score(existing));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Score(Combine c)
|
||||||
|
{
|
||||||
|
if (c.Materials.Length is 1 && c.Materials[0].Count is 3 && c.Result.Count is 1)
|
||||||
|
{
|
||||||
|
return c.RecipeType switch
|
||||||
|
{
|
||||||
|
RecipeType.RECIPE_TYPE_COMBINE => 300,
|
||||||
|
RecipeType.RECIPE_TYPE_CONVERT => 200,
|
||||||
|
_ => 150,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.RecipeType is RecipeType.RECIPE_TYPE_COMBINE)
|
||||||
|
{
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-5
@@ -216,12 +216,17 @@ internal static class MetadataServiceImmutableDictionaryExtension
|
|||||||
token);
|
token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<ImmutableDictionary<MaterialId, Combine>> GetResultMaterialIdToCombineMapAsync(CancellationToken token = default)
|
public async ValueTask<ImmutableDictionary<MaterialId, Combine>> GetResultMaterialIdToCombineMapAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
return metadataService.FromCacheAsDictionaryAsync<MaterialId, Combine>(
|
string cacheKey = $"{nameof(MetadataService)}.Cache.{MetadataFileStrategies.Combine.Name}.Map.{nameof(MaterialId)}.{nameof(Combine)}.PreferThreeToOne";
|
||||||
MetadataFileStrategies.Combine,
|
ImmutableDictionary<MaterialId, Combine>? result = await metadataService.MemoryCache.GetOrCreateAsync(cacheKey, async entry =>
|
||||||
c => c.Result.Id,
|
{
|
||||||
token);
|
ImmutableArray<Combine> array = await metadataService.FromCacheOrFileAsync<Combine>(MetadataFileStrategies.Combine, token).ConfigureAwait(false);
|
||||||
|
return CombineResultMaterialIdMapFactory.ToImmutableDictionary(array);
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueTask<ImmutableDictionary<TKey, TValue>> FromCacheAsDictionaryAsync<TKey, TValue>(MetadataFileStrategy strategy, CancellationToken token)
|
private ValueTask<ImmutableDictionary<TKey, TValue>> FromCacheAsDictionaryAsync<TKey, TValue>(MetadataFileStrategy strategy, CancellationToken token)
|
||||||
|
|||||||
Reference in New Issue
Block a user