server-master/srcs/_plugins/WingsEmu.Plugins.BasicImplementation/Managers/GroupManager.cs
2026-02-10 18:21:30 +01:00

199 lines
No EOL
5.8 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using PhoenixLib.Logging;
using WingsAPI.Game.Extensions.Groups;
using WingsEmu.Game._ItemUsage.Configuration;
using WingsEmu.Game.Characters;
using WingsEmu.Game.Groups;
namespace WingsEmu.Plugins.BasicImplementations.Managers;
public sealed class GroupManager : IGroupManager
{
private readonly List<PlayerGroup> _groups;
private readonly ConcurrentQueue<(IPlayerEntity, PlayerGroup)> _groupsToAdd = new();
private readonly ConcurrentQueue<(IPlayerEntity, PlayerGroup)> _groupsToRemove = new();
private readonly ConcurrentQueue<(long, PlayerGroup)> _leaderToChange = new();
private readonly ConcurrentQueue<(IPlayerEntity, PlayerGroup)> _playersToAdd = new();
private readonly ConcurrentQueue<(IPlayerEntity, PlayerGroup)> _playersToRemove = new();
private readonly ISpPartnerConfiguration _spPartnerConfiguration;
private int _lastGroupId;
private DateTime _lastGroupUiRefresh;
public GroupManager(ISpPartnerConfiguration spPartnerConfiguration)
{
_spPartnerConfiguration = spPartnerConfiguration;
_groups = new List<PlayerGroup>();
_lastGroupUiRefresh = DateTime.MinValue;
Id = Guid.NewGuid();
}
public Guid Id { get; }
public string Name => nameof(GroupManager);
public void ProcessTick(DateTime date)
{
RemoveGroup();
AddNewGroup();
PlayerRemoveFromGroup();
PlayerAddToGroup();
ChangeLeader();
if (_lastGroupUiRefresh.AddSeconds(1) > date)
{
return;
}
_lastGroupUiRefresh = DateTime.UtcNow;
var stopWatch = Stopwatch.StartNew();
ProcessGroupRefresh();
stopWatch.Stop();
}
public int GetNextGroupId()
{
Interlocked.Increment(ref _lastGroupId);
return _lastGroupId;
}
public void JoinGroup(PlayerGroup group, IPlayerEntity character)
{
_groupsToAdd.Enqueue((character, group));
}
public void RemoveGroup(PlayerGroup group, IPlayerEntity character)
{
_groupsToRemove.Enqueue((character, group));
}
public void AddMemberGroup(PlayerGroup group, IPlayerEntity character)
{
_playersToAdd.Enqueue((character, group));
}
public void RemoveMemberGroup(PlayerGroup group, IPlayerEntity character)
{
_playersToRemove.Enqueue((character, group));
}
public void ChangeLeader(PlayerGroup group, long newLeaderId)
{
_leaderToChange.Enqueue((newLeaderId, group));
}
private void ProcessGroupRefresh()
{
foreach (PlayerGroup group in _groups)
{
try
{
IReadOnlyList<IPlayerEntity> groupMembers = group.Members;
foreach (IPlayerEntity member in groupMembers)
{
member.Session.RefreshPartyUi();
}
}
catch (Exception e)
{
Log.Error("Group.RefreshMembers", e);
}
}
}
private void RemoveGroup()
{
while (_groupsToRemove.TryDequeue(out (IPlayerEntity, PlayerGroup) playerGroup))
{
PlayerGroup group = playerGroup.Item2;
IPlayerEntity character = playerGroup.Item1;
character.RemoveGroup();
foreach (IPlayerEntity member in group.Members)
{
member.Session.RefreshParty(_spPartnerConfiguration);
member.Session.BroadcastPidx();
}
_groups.Remove(group);
}
}
private void AddNewGroup()
{
while (_groupsToAdd.TryDequeue(out (IPlayerEntity, PlayerGroup) playerGroup))
{
IPlayerEntity character = playerGroup.Item1;
PlayerGroup group = playerGroup.Item2;
_groups.Add(group);
character.SetGroup(group);
foreach (IPlayerEntity member in group.Members)
{
member.Session.RefreshParty(_spPartnerConfiguration);
if (!member.IsLeaderOfGroup(member.Id))
{
continue;
}
member.Session.BroadcastPidx();
}
}
}
private void PlayerRemoveFromGroup()
{
while (_playersToRemove.TryDequeue(out (IPlayerEntity, PlayerGroup) playerGroup))
{
IPlayerEntity character = playerGroup.Item1;
PlayerGroup group = playerGroup.Item2;
group.RemoveMember(character);
character.RemoveGroup();
character.Session.RefreshParty(_spPartnerConfiguration);
character.Session.BroadcastPidx();
foreach (IPlayerEntity member in group.Members)
{
member.Session.RefreshParty(_spPartnerConfiguration);
member.Session.BroadcastPidx();
}
}
}
private void PlayerAddToGroup()
{
while (_playersToAdd.TryDequeue(out (IPlayerEntity character, PlayerGroup) playerGroup))
{
IPlayerEntity character = playerGroup.Item1;
PlayerGroup group = playerGroup.Item2;
character.SetGroup(group);
group.AddMember(character);
foreach (IPlayerEntity member in group.Members)
{
member.Session.RefreshParty(_spPartnerConfiguration);
if (character.Id != member.Id)
{
continue;
}
member.Session.BroadcastPidx();
}
}
}
private void ChangeLeader()
{
while (_leaderToChange.TryDequeue(out (long, PlayerGroup) playerGroup))
{
playerGroup.Item2.OwnerId = playerGroup.Item1;
}
}
}