namespace Ananta.Server.Protocol.Client4229938;
///
/// Per-character weapon-skin assignments (spiritId -> weapon sceneItemId -> skinId), held on
/// so a re-login replays them (硬规则 2). The donor keeps this in a
/// process-wide static that resets on restart; here it rides the same snapshot as the outfit and the
/// dye, so dressing a character actually survives.
///
/// ⛑⛑ Like the dye, nothing is pushed when the player assigns a skin: the client commits locally on
/// err=0 and the state is replayed through the login seed
/// (PlayerWeaponSkinInfo.SpiritWeaponSkinDict).
///
internal static class WeaponSkinStore
{
internal static Dictionary GetEquipped(WorldEntryState? state, uint spiritId)
{
if (state is null)
return [];
lock (state.SyncRoot)
return state.WeaponSkins.TryGetValue(spiritId, out var record)
? new Dictionary(record.SkinBySceneItem)
: [];
}
/// Assigns one skin to every listed weapon of a character.
internal static void SetSkin(
WorldEntryState state, uint spiritId, IEnumerable sceneItemIds, uint skinId)
{
lock (state.SyncRoot)
{
var current = state.WeaponSkins.TryGetValue(spiritId, out var record)
? new Dictionary(record.SkinBySceneItem)
: [];
foreach (var sceneItemId in sceneItemIds)
{
if (sceneItemId == 0)
continue;
current[sceneItemId] = skinId;
}
state.WeaponSkins[spiritId] = new WeaponSkinRecord4229938(current);
}
}
/// Copies one character's whole skin set onto the target characters ("apply to all").
internal static void SetAll(WorldEntryState state, uint spiritId, Dictionary skinBySceneItem)
{
lock (state.SyncRoot)
state.WeaponSkins[spiritId] = new WeaponSkinRecord4229938(new Dictionary(skinBySceneItem));
}
/// Everything worn right now: spiritId -> (sceneItemId -> skinId), for the login seed.
internal static Dictionary> Snapshot(WorldEntryState? state)
{
var result = new Dictionary>();
if (state is null)
return result;
lock (state.SyncRoot)
{
foreach (var (spiritId, record) in state.WeaponSkins)
{
if (spiritId == 0 || record?.SkinBySceneItem is null || record.SkinBySceneItem.Count == 0)
continue;
result[spiritId] = new Dictionary(record.SkinBySceneItem);
}
}
return result;
}
}