234 lines
No EOL
8.9 KiB
C#
234 lines
No EOL
8.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using PhoenixLib.Caching;
|
|
using PhoenixLib.DAL.Redis.Locks;
|
|
using PhoenixLib.Logging;
|
|
using Plugin.FamilyImpl.Logs;
|
|
using WingsAPI.Communication.Families;
|
|
using WingsAPI.Data.Families;
|
|
using WingsEmu.Game.Families;
|
|
using WingsEmu.Game.Managers;
|
|
using WingsEmu.Game.Networking;
|
|
using WingsEmu.Packets.Enums.Families;
|
|
|
|
namespace Plugin.FamilyImpl
|
|
{
|
|
public class FamilyManager : IFamilyManager
|
|
{
|
|
private readonly IExpirableLockService _expirableLockService;
|
|
private readonly IKeyValueCache<IFamily> _familyByName;
|
|
private readonly ILongKeyCachedRepository<Family> _familyCache;
|
|
private readonly IFamilyExperienceManager _familyExperienceManager;
|
|
private readonly IFamilyLogManager _familyLogManager;
|
|
private readonly IFamilyService _familyService;
|
|
|
|
private readonly ReaderWriterLockSlim _lock = new();
|
|
private readonly ILongKeyCachedRepository<FamilyMembership> _membershipCache;
|
|
private readonly ISessionManager _sessionManager;
|
|
|
|
public FamilyManager(ILongKeyCachedRepository<Family> familyCache, IFamilyService familyService, ISessionManager sessionManager, ILongKeyCachedRepository<FamilyMembership> membershipCache,
|
|
IFamilyLogManager familyLogManager, IFamilyExperienceManager familyExperienceManager, IKeyValueCache<IFamily> familyByName, IExpirableLockService expirableLockService)
|
|
{
|
|
_familyCache = familyCache;
|
|
_familyService = familyService;
|
|
_sessionManager = sessionManager;
|
|
_membershipCache = membershipCache;
|
|
_familyLogManager = familyLogManager;
|
|
_familyExperienceManager = familyExperienceManager;
|
|
_familyByName = familyByName;
|
|
_expirableLockService = expirableLockService;
|
|
}
|
|
|
|
public void AddFamily(FamilyDTO family, IReadOnlyCollection<FamilyMembershipDto> members)
|
|
{
|
|
IFamily oldFamily = _familyCache.Get(family.Id);
|
|
var newFamily = new Family(family, members, new List<FamilyLogDto>(), _sessionManager);
|
|
_familyCache.Set(family.Id, newFamily);
|
|
_familyByName.Set(family.Name, newFamily);
|
|
if (oldFamily == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
newFamily.Members.AddRange(oldFamily.Members);
|
|
oldFamily.Members.Clear();
|
|
}
|
|
|
|
public void RemoveFamily(long familyId)
|
|
{
|
|
IFamily cachedFamily = _familyCache.Get(familyId);
|
|
_familyCache.Remove(familyId);
|
|
|
|
foreach (FamilyMembership member in cachedFamily.Members)
|
|
{
|
|
_membershipCache.Remove(member.CharacterId);
|
|
IClientSession session = _sessionManager.GetSessionByCharacterId(member.CharacterId);
|
|
session?.PlayerEntity.SetFamilyMembership(null);
|
|
}
|
|
}
|
|
|
|
public IFamily GetFamilyByFamilyName(string familyName) => _familyByName.Get(familyName);
|
|
|
|
public void AddOrReplaceMember(FamilyMembershipDto membership, IFamily family)
|
|
{
|
|
if (family == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var newMember = new FamilyMembership(membership, _sessionManager);
|
|
family.Members.RemoveAll(x => x.CharacterId == membership.CharacterId);
|
|
_membershipCache.Set(newMember.CharacterId, newMember);
|
|
if (newMember.Authority == FamilyAuthority.Head)
|
|
{
|
|
family.Head = newMember;
|
|
}
|
|
|
|
family.Members.Add(newMember);
|
|
IClientSession session = _sessionManager.GetSessionByCharacterId(membership.CharacterId);
|
|
session?.PlayerEntity.SetFamilyMembership(newMember);
|
|
}
|
|
|
|
public void AddOrReplaceMember(FamilyMembershipDto membership)
|
|
{
|
|
AddOrReplaceMember(membership, GetFamilyByFamilyId(membership.FamilyId));
|
|
}
|
|
|
|
public void RemoveMember(long characterId, long familyId)
|
|
{
|
|
IFamily family = GetFamilyByFamilyId(familyId);
|
|
family?.Members.RemoveAll(x => x.CharacterId == characterId);
|
|
|
|
_membershipCache.Remove(characterId);
|
|
IClientSession session = _sessionManager.GetSessionByCharacterId(characterId);
|
|
session?.PlayerEntity.SetFamilyMembership(null);
|
|
}
|
|
|
|
public void MemberDisconnectionUpdate(long characterId, DateTime disconnectionTime)
|
|
{
|
|
FamilyMembership member = GetFamilyMembershipByCharacterId(characterId);
|
|
if (member == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
member.LastOnlineDate = disconnectionTime;
|
|
AddOrReplaceMember(member);
|
|
}
|
|
|
|
public FamilyMembership GetFamilyMembershipByCharacterId(long characterId)
|
|
{
|
|
FamilyMembership membership = _membershipCache.Get(characterId);
|
|
if (membership != null)
|
|
{
|
|
return membership;
|
|
}
|
|
|
|
MembershipResponse response = _familyService.GetMembershipByCharacterIdAsync(
|
|
new MembershipRequest { CharacterId = characterId }).ConfigureAwait(false).GetAwaiter().GetResult();
|
|
|
|
return response.Membership == null ? null : _membershipCache.GetOrSet(response.Membership.CharacterId, () => new FamilyMembership(response.Membership, _sessionManager));
|
|
}
|
|
|
|
public void AddToFamilyLogs(IReadOnlyDictionary<long, List<FamilyLogDto>> logs)
|
|
{
|
|
try
|
|
{
|
|
foreach (KeyValuePair<long, List<FamilyLogDto>> familyLogs in logs)
|
|
{
|
|
IFamily family = _familyCache.Get(familyLogs.Key);
|
|
if (family == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_lock.EnterWriteLock();
|
|
try
|
|
{
|
|
foreach (FamilyLogDto log in familyLogs.Value)
|
|
{
|
|
family.Logs.Add(log);
|
|
}
|
|
|
|
family.Logs.Sort((x, y) => DateTime.Compare(y.Timestamp, x.Timestamp)); // Newest -> Older
|
|
|
|
if (family.Logs.Count <= 200)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (int i = 200; i < family.Logs.Count; i++)
|
|
{
|
|
family.Logs.RemoveAt(i);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
_lock.ExitWriteLock();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error("[FAMILY_MANAGER] AddToFamilyLogs", e);
|
|
}
|
|
}
|
|
|
|
public void SendLogToFamilyServer(FamilyLogDto log)
|
|
{
|
|
_familyLogManager.SaveLogToBuffer(log);
|
|
}
|
|
|
|
public IEnumerable<long> AddToFamilyExperiences(Dictionary<long, long> exps)
|
|
{
|
|
var familyIds = new HashSet<long>();
|
|
|
|
foreach ((long characterId, long experience) in exps)
|
|
{
|
|
FamilyMembership membership = _membershipCache.Get(characterId);
|
|
if (membership == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
membership.Experience = experience;
|
|
familyIds.Add(membership.FamilyId);
|
|
}
|
|
|
|
return familyIds;
|
|
}
|
|
|
|
public void SendExperienceToFamilyServer(ExperienceGainedSubMessage experienceGainedSubMessage)
|
|
{
|
|
_familyExperienceManager.SaveFamilyExperienceToBuffer(experienceGainedSubMessage);
|
|
}
|
|
|
|
public async Task<bool> CanJoinNewFamilyAsync(int playerEntityId) =>
|
|
await _expirableLockService.TryAddTemporaryLockAsync($"game:locks:character:{playerEntityId}:join-family", DateTime.UtcNow.Date.AddDays(1));
|
|
|
|
public async Task<bool> RemovePlayerJoinCooldownAsync(int playerEntityId) => await _expirableLockService.TryRemoveTemporaryLock($"game:locks:character:{playerEntityId}:join-family");
|
|
|
|
public Family GetFamilyByFamilyId(long familyId)
|
|
{
|
|
Family family = _familyCache.Get(familyId);
|
|
if (family != null)
|
|
{
|
|
return family;
|
|
}
|
|
|
|
FamilyIdResponse response = _familyService.GetFamilyByIdAsync(new FamilyIdRequest { FamilyId = familyId }).ConfigureAwait(false).GetAwaiter().GetResult();
|
|
family = _familyCache.GetOrSet(familyId, () => new Family(response.Family, response.Members, response.Logs, _sessionManager));
|
|
_familyByName.Set(family.Name, family);
|
|
foreach (FamilyMembership member in family.Members)
|
|
{
|
|
_membershipCache.Set(member.CharacterId, member);
|
|
}
|
|
|
|
return family;
|
|
}
|
|
|
|
public Family GetFamilyByFamilyIdCache(long familyId) => _familyCache.Get(familyId);
|
|
}
|
|
} |