feat: Upgrade server with HyNB v2.4 modular architecture, minigames, admin GM web panel, companion summons, and car radio
This commit is contained in:
1 parent
74e2963a12
commit
3e5adf1dc5
1571 files changed
+336468
-6348
No files matched your search
@@ -0,0 +1,75 @@
|
||||
namespace Ananta.Server.Protocol.Client4229938;
|
||||
|
||||
/// <summary>
|
||||
/// Per-character weapon-skin assignments (spiritId -> weapon sceneItemId -> skinId), held on
|
||||
/// <see cref="WorldEntryState"/> 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
|
||||
/// (<c>PlayerWeaponSkinInfo.SpiritWeaponSkinDict</c>).
|
||||
/// </summary>
|
||||
internal static class WeaponSkinStore
|
||||
{
|
||||
internal static Dictionary<uint, uint> GetEquipped(WorldEntryState? state, uint spiritId)
|
||||
{
|
||||
if (state is null)
|
||||
return [];
|
||||
|
||||
lock (state.SyncRoot)
|
||||
return state.WeaponSkins.TryGetValue(spiritId, out var record)
|
||||
? new Dictionary<uint, uint>(record.SkinBySceneItem)
|
||||
: [];
|
||||
}
|
||||
|
||||
/// <summary>Assigns one skin to every listed weapon of a character.</summary>
|
||||
internal static void SetSkin(
|
||||
WorldEntryState state, uint spiritId, IEnumerable<uint> sceneItemIds, uint skinId)
|
||||
{
|
||||
lock (state.SyncRoot)
|
||||
{
|
||||
var current = state.WeaponSkins.TryGetValue(spiritId, out var record)
|
||||
? new Dictionary<uint, uint>(record.SkinBySceneItem)
|
||||
: [];
|
||||
|
||||
foreach (var sceneItemId in sceneItemIds)
|
||||
{
|
||||
if (sceneItemId == 0)
|
||||
continue;
|
||||
|
||||
current[sceneItemId] = skinId;
|
||||
}
|
||||
|
||||
state.WeaponSkins[spiritId] = new WeaponSkinRecord4229938(current);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Copies one character's whole skin set onto the target characters ("apply to all").</summary>
|
||||
internal static void SetAll(WorldEntryState state, uint spiritId, Dictionary<uint, uint> skinBySceneItem)
|
||||
{
|
||||
lock (state.SyncRoot)
|
||||
state.WeaponSkins[spiritId] = new WeaponSkinRecord4229938(new Dictionary<uint, uint>(skinBySceneItem));
|
||||
}
|
||||
|
||||
/// <summary>Everything worn right now: spiritId -> (sceneItemId -> skinId), for the login seed.</summary>
|
||||
internal static Dictionary<uint, Dictionary<uint, uint>> Snapshot(WorldEntryState? state)
|
||||
{
|
||||
var result = new Dictionary<uint, Dictionary<uint, uint>>();
|
||||
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<uint, uint>(record.SkinBySceneItem);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user