using System.Text.Json; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using RadicadeServer.DB; using RadicadeServer.Extensions; using RadicadeServer.RecNet.Accounts; using RadicadeServer.RecNet.Avatar; namespace RadicadeServer.API.Avatars.V1; [Route("api/equipment/v1")] [Route("econ/api/equipment/v1")] [Authorize] public class EquipmentV1(RecDBContext db) : Controller { [HttpPost("update")] [HttpPut("update")] public async Task UpdateEquipment([FromBody] JsonElement body) { var userId = User.GetUserId(); if (userId == null) return Unauthorized(); if (!TryParse(body, out var entries)) return BadRequest(); var slots = entries.Where(entry => entry.HasSlot).ToList(); var favourites = entries.Where(entry => entry.Favorited.HasValue).ToList(); if (slots.Count == 0 && favourites.Count == 0) return Ok(); if (slots.Count > 0) { var avatar = await db.Avatars.FirstOrDefaultAsync(x => x.AccountId == userId); if (avatar != null) { avatar.EquipmentSlots = slots.Select(entry => (object)new { slotIndex = entry.SlotIndex, equipmentPrefabName = entry.PrefabName ?? string.Empty, equipmentModificationGuid = entry.ModificationGuid ?? string.Empty }).ToList().ToJson(); } } if (favourites.Count > 0) await ApplyFavouritesAsync(userId.Value, favourites); await db.SaveChangesAsync(); return Ok(); } private async Task ApplyFavouritesAsync(long userId, List favourites) { var unlocks = await db.Unlocks.FirstOrDefaultAsync(x => x.AccountId == userId); if (unlocks == null) { unlocks = new PlayerUnlocks { AccountId = userId }; db.Unlocks.Add(unlocks); } List equipment; try { equipment = unlocks.GetEquipment() ?? new List(); } catch (JsonException) { equipment = new List(); } foreach (var update in favourites) { if (string.IsNullOrWhiteSpace(update.ModificationGuid)) continue; var row = equipment.FirstOrDefault(item => string.Equals( item.ModificationGuid, update.ModificationGuid, StringComparison.OrdinalIgnoreCase)); if (row == null) { continue; } row.Favorited = update.Favorited == true; } unlocks.Equipment = equipment.ToJson(); } private sealed class EquipmentUpdate { public string? PrefabName { get; set; } public string? ModificationGuid { get; set; } public bool? Favorited { get; set; } public int SlotIndex { get; set; } public bool HasSlot { get; set; } } private static bool TryParse(JsonElement body, out List entries) { entries = new List(); JsonElement array; if (body.ValueKind == JsonValueKind.Array) { array = body; } else if (body.ValueKind == JsonValueKind.Object) { var found = false; array = default; foreach (var prop in body.EnumerateObject()) { if (string.Equals(prop.Name, "equipmentSlots", StringComparison.OrdinalIgnoreCase) && prop.Value.ValueKind == JsonValueKind.Array) { array = prop.Value; found = true; break; } } if (!found) return false; } else { return false; } foreach (var item in array.EnumerateArray()) { if (item.ValueKind != JsonValueKind.Object) continue; var entry = new EquipmentUpdate(); foreach (var prop in item.EnumerateObject()) { if (string.Equals(prop.Name, "slotIndex", StringComparison.OrdinalIgnoreCase) || string.Equals(prop.Name, "slot", StringComparison.OrdinalIgnoreCase) || string.Equals(prop.Name, "index", StringComparison.OrdinalIgnoreCase)) { if (prop.Value.ValueKind == JsonValueKind.Number) entry.SlotIndex = prop.Value.GetInt32(); entry.HasSlot = true; } else if (string.Equals(prop.Name, "favorited", StringComparison.OrdinalIgnoreCase) || string.Equals(prop.Name, "favourite", StringComparison.OrdinalIgnoreCase)) { if (prop.Value.ValueKind == JsonValueKind.True) entry.Favorited = true; else if (prop.Value.ValueKind == JsonValueKind.False) entry.Favorited = false; } else if (string.Equals(prop.Name, "modificationGuid", StringComparison.OrdinalIgnoreCase) || string.Equals(prop.Name, "equipmentModificationGuid", StringComparison.OrdinalIgnoreCase)) { if (prop.Value.ValueKind == JsonValueKind.String) entry.ModificationGuid = prop.Value.GetString(); } else if (string.Equals(prop.Name, "prefabName", StringComparison.OrdinalIgnoreCase) || string.Equals(prop.Name, "equipmentPrefabName", StringComparison.OrdinalIgnoreCase) || string.Equals(prop.Name, "equipment", StringComparison.OrdinalIgnoreCase)) { if (prop.Value.ValueKind == JsonValueKind.String) entry.PrefabName = prop.Value.GetString(); } } entries.Add(entry); } return true; } }