199 lines
No EOL
5.8 KiB
C#
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;
|
|
}
|
|
}
|
|
} |