using System.Text.Json; using Yuanshen.Protocol; namespace Yuanshen.Gameserver.Game; internal readonly record struct GadgetNode( uint NodeId, uint ConfigId, uint GroupId, uint GadgetId, uint Level, Vector Pos, Vector Rot, string Kind, uint State, uint GadgetType, uint DropId, uint GatherItemId, uint SubfieldId, uint MarkFlag) { public bool IsChest => Kind == "chest"; public bool IsDrop => Kind == "drop"; } internal sealed class GadgetSpawnTable { public IReadOnlyList Nodes { get; } public GadgetSpawnTable() { Nodes = Load("scene3_gadgets.json"); } private static List Load(string fileName) { List nodes = new(); string path = Path.Combine(AppContext.BaseDirectory, "assets", "scene", fileName); if (!File.Exists(path)) return nodes; using JsonDocument document = JsonDocument.Parse(File.ReadAllText(path)); foreach (JsonElement row in document.RootElement.EnumerateArray()) { string kind = row.TryGetProperty("k", out JsonElement k) ? k.GetString() ?? string.Empty : string.Empty; if (kind.Length == 0) continue; nodes.Add(new GadgetNode( Number(row, "n"), Number(row, "c"), Number(row, "g"), Number(row, "gi"), Math.Max(Number(row, "l"), 1u), new Vector { X = Real(row, "x"), Y = Real(row, "y"), Z = Real(row, "z") }, new Vector { X = Real(row, "rx"), Y = Real(row, "ry"), Z = Real(row, "rz") }, kind, Number(row, "st"), Number(row, "ty"), Number(row, "rd"), Number(row, "ii"), Subfield(row), Number(row, "mf"))); } return nodes; } private static uint Subfield(JsonElement row) { if (!row.TryGetProperty("sf", out JsonElement subfields)) return 0; foreach (JsonProperty entry in subfields.EnumerateObject()) return entry.Value.GetUInt32(); return 0; } private static uint Number(JsonElement row, string name) => row.TryGetProperty(name, out JsonElement value) && value.TryGetUInt32(out uint parsed) ? parsed : 0; private static float Real(JsonElement row, string name) => row.TryGetProperty(name, out JsonElement value) ? (float)value.GetDouble() : 0f; }