Files
Campus-25/server/Server/2025-RecRoom-Server-E12354-main/api/dbs/EquipmentDB.cs
T
2026-10-14 06:59:51 +02:00

83 lines
3.5 KiB
C#

using LiteDB;
namespace Campus_live_rewrite.api.dbs
{
// What each player has equipped, per equipment prefab.
//
// The client POSTs /api/equipment/v1/update every time a skin is equipped, sending
// the full entry for that prefab:
//
// [{"PrefabName":"[ShareCamera]","ModificationGuid":"48c97ace-...",
// "FriendlyName":"Camping Share Camera","Tooltip":"","Rarity":0,
// "ThumbnailImageName":null,"Favorited":true}]
//
// That route did not exist, so the POST 404'd and the choice lived only in the
// running client - at the next login everyone was back on the default skin.
//
// Stored as a collection inside Players.db rather than its own file, so it rides the
// existing checkpoint (DbMaintenance.CheckpointAll) instead of adding another
// write-ahead log that never gets merged.
public static class EquipmentDB
{
public class EquippedItem
{
public string PrefabName { get; set; } = "";
public string ModificationGuid { get; set; } = "";
public string? FriendlyName { get; set; }
public string? Tooltip { get; set; }
public int Rarity { get; set; }
public string? ThumbnailImageName { get; set; }
public bool Favorited { get; set; }
}
public class PlayerEquipment
{
[BsonId]
public ulong PlayerId { get; set; }
public List<EquippedItem> Equipped { get; set; } = new();
}
private static readonly ILiteCollection<PlayerEquipment> _col =
PlayerDB.PlayerDBFile.GetCollection<PlayerEquipment>("player_equipment");
public static List<EquippedItem> Get(ulong playerId) =>
_col.FindById(playerId)?.Equipped ?? new List<EquippedItem>();
/// <summary>
/// Records the state the client just sent, keyed by prefab AND modification guid.
/// Returns the player's full loadout afterwards.
///
/// Keying by prefab alone loses data. One request carries SEVERAL entries for the
/// same prefab - the newly equipped skin, plus the one it replaced so its flag can
/// be cleared:
///
/// [MakerPen] Professor Maker Pen (the new one)
/// [MakerPen] Host 2 Maker Pen (the old one, flag being cleared)
///
/// Replacing "all entries for [MakerPen]" therefore kept only whichever happened to
/// come LAST in the array - frequently the one being switched OFF - so the skin came
/// back unequipped. The client decides which entry is current; our job is to store
/// exactly what it told us, per item.
/// </summary>
public static List<EquippedItem> Update(ulong playerId, IEnumerable<EquippedItem>? items)
{
var row = _col.FindById(playerId) ?? new PlayerEquipment { PlayerId = playerId };
if (items == null) return row.Equipped;
foreach (var item in items)
{
if (item == null || string.IsNullOrWhiteSpace(item.PrefabName)) continue;
row.Equipped.RemoveAll(e =>
string.Equals(e.PrefabName, item.PrefabName, StringComparison.OrdinalIgnoreCase) &&
string.Equals(e.ModificationGuid, item.ModificationGuid, StringComparison.OrdinalIgnoreCase));
row.Equipped.Add(item);
}
_col.Upsert(row);
return row.Equipped;
}
}
}