83 lines
3.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|