mirror of
https://github.com/waynebian01/Shigure.git
synced 2026-09-03 07:15:24 +08:00
- Removed the UnitSelector class from UI and added a new UnitSelector class in Modules. - Introduced RuntimeSessionCoordinator to manage runtime sessions, ensuring safe concurrent operations. - Created ShigureRuntimeFactory to handle the creation of ShigureRuntime instances. - Added WindowsTriggerKeyState and WindowsVirtualKeyMap for handling key states and virtual key mappings. - Implemented IKeymapResolver interface for key mapping resolution. - Established runtime dependencies with interfaces for screen scanning, state building, logic evaluation, and key output.
149 lines
5.4 KiB
C#
149 lines
5.4 KiB
C#
using System.Text.Json.Nodes;
|
||
|
||
namespace Shigure;
|
||
|
||
public sealed class StateBuilder : IRuntimeStateBuilder
|
||
{
|
||
private readonly ConfigService _config;
|
||
|
||
public StateBuilder(ConfigService config)
|
||
{
|
||
_config = config;
|
||
}
|
||
|
||
public GameState Build(
|
||
IReadOnlyDictionary<int, int> rowData,
|
||
IReadOnlyDictionary<int, int> barData,
|
||
IReadOnlyDictionary<int, int>? healAbsorbData = null)
|
||
{
|
||
var classId = rowData.TryGetValue(2, out var cid) ? cid : 0;
|
||
var specId = rowData.TryGetValue(3, out var sid) ? sid : 0;
|
||
var stateConfig = _config.BuildStateConfig(classId, specId);
|
||
var result = new Dictionary<string, object?>();
|
||
healAbsorbData ??= new Dictionary<int, int>();
|
||
|
||
foreach (var (key, node) in stateConfig)
|
||
{
|
||
if (key is "group" or "spells" or "auras" || node is not JsonObject field || !field.ContainsKey("step"))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
result[key] = ConvertRawValue(ResolveRaw(field, rowData, barData), JsonHelpers.GetString(JsonHelpers.Get(field, "type")));
|
||
}
|
||
|
||
if (JsonHelpers.Get(stateConfig, "spells") is JsonObject spellsConfig)
|
||
{
|
||
result["spells"] = BuildFieldMap(spellsConfig, rowData, barData);
|
||
}
|
||
|
||
if (JsonHelpers.Get(stateConfig, "auras") is JsonObject aurasConfig)
|
||
{
|
||
result["auras"] = BuildFieldMap(aurasConfig, rowData, barData);
|
||
}
|
||
|
||
if (JsonHelpers.Get(stateConfig, "group") is JsonObject groupConfig)
|
||
{
|
||
var group = BuildGroup(groupConfig, rowData, barData, healAbsorbData);
|
||
result["group"] = group;
|
||
}
|
||
|
||
return new GameState(result);
|
||
}
|
||
|
||
private static Dictionary<string, object?> BuildFieldMap(
|
||
JsonObject fieldsConfig,
|
||
IReadOnlyDictionary<int, int> rowData,
|
||
IReadOnlyDictionary<int, int> barData)
|
||
{
|
||
var values = new Dictionary<string, object?>();
|
||
foreach (var (fieldName, node) in fieldsConfig)
|
||
{
|
||
if (node is not JsonObject field || !field.ContainsKey("step"))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
values[fieldName] = ConvertRawValue(ResolveRaw(field, rowData, barData), JsonHelpers.GetString(JsonHelpers.Get(field, "type")));
|
||
}
|
||
|
||
return values;
|
||
}
|
||
|
||
private static Dictionary<string, IReadOnlyDictionary<string, object?>> BuildGroup(
|
||
JsonObject groupConfig,
|
||
IReadOnlyDictionary<int, int> rowData,
|
||
IReadOnlyDictionary<int, int> barData,
|
||
IReadOnlyDictionary<int, int> healAbsorbData)
|
||
{
|
||
var start = JsonHelpers.GetInt(JsonHelpers.Get(groupConfig, "start")) ?? 26;
|
||
var numParams = JsonHelpers.GetInt(JsonHelpers.Get(groupConfig, "num")) ?? 5;
|
||
var group = new Dictionary<string, IReadOnlyDictionary<string, object?>>();
|
||
|
||
for (var i = 1; i <= 30; i++)
|
||
{
|
||
var baseStep = start + (i - 1) * numParams;
|
||
var sub = new Dictionary<string, object?>();
|
||
foreach (var (fieldName, node) in groupConfig)
|
||
{
|
||
if (fieldName is "start" or "num" || node is not JsonObject field || !field.ContainsKey("step"))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
int? raw;
|
||
var stepNode = JsonHelpers.Get(field, "step");
|
||
if (JsonHelpers.GetString(stepNode) == "bar")
|
||
{
|
||
raw = ResolveRaw(field, rowData, barData);
|
||
}
|
||
else
|
||
{
|
||
var relStep = JsonHelpers.GetInt(stepNode);
|
||
raw = relStep is null
|
||
? null
|
||
: rowData.TryGetValue(baseStep + relStep.Value, out var rawValue) ? rawValue : null;
|
||
}
|
||
|
||
sub[fieldName] = ConvertRawValue(raw, JsonHelpers.GetString(JsonHelpers.Get(field, "type")));
|
||
}
|
||
|
||
// 治疗吸收来自网格扫描:白块右侧像素的 B=单位编号,G-1=吸收值。
|
||
// 插件像素里的生命值含吸收盾,这里折算为真实生命:生命值 -= 治疗吸收。
|
||
var absorb = healAbsorbData.TryGetValue(i, out var absorbValue) ? absorbValue : 0;
|
||
sub["治疗吸收"] = absorb;
|
||
if (absorb != 0 && sub.TryGetValue("生命值", out var healthObj) && healthObj is int health)
|
||
{
|
||
sub["生命值"] = Math.Max(0, health - absorb);
|
||
}
|
||
|
||
group[i.ToString()] = sub;
|
||
}
|
||
|
||
return group;
|
||
}
|
||
|
||
private static int? ResolveRaw(JsonObject field, IReadOnlyDictionary<int, int> rowData, IReadOnlyDictionary<int, int> barData)
|
||
{
|
||
var stepNode = JsonHelpers.Get(field, "step");
|
||
if (JsonHelpers.GetString(stepNode) == "bar")
|
||
{
|
||
var barIndex = JsonHelpers.GetInt(JsonHelpers.Get(field, "bar"));
|
||
return barIndex is not null && barData.TryGetValue(barIndex.Value, out var barValue) ? barValue : null;
|
||
}
|
||
|
||
var step = JsonHelpers.GetInt(stepNode);
|
||
return step is not null && rowData.TryGetValue(step.Value, out var value) ? value : null;
|
||
}
|
||
|
||
private static object ConvertRawValue(int? raw, string? type)
|
||
{
|
||
return type switch
|
||
{
|
||
"bool" => raw.GetValueOrDefault() != 0,
|
||
"string" => raw?.ToString() ?? string.Empty,
|
||
_ => raw.GetValueOrDefault()
|
||
};
|
||
}
|
||
}
|