using System.Threading; using System.Threading.Tasks; using PhoenixLib.Events; using PhoenixLib.Logging; using WingsAPI.Game.Extensions.ItemExtension.Item; using WingsAPI.Packets.Enums; using WingsEmu.DTOs.Maps; using WingsEmu.Game._enum; using WingsEmu.Game._i18n; using WingsEmu.Game.Extensions; using WingsEmu.Game.Managers; using WingsEmu.Game.Managers.StaticData; using WingsEmu.Game.Networking; using WingsEmu.Game.Raids; using WingsEmu.Game.Raids.Enum; using WingsEmu.Game.Raids.Events; using WingsEmu.Game.Relations; using WingsEmu.Packets.Enums; using WingsEmu.Packets.Enums.Chat; namespace Plugin.Raids; public class RaidPartyJoinEventHandler : IAsyncEventProcessor { private static readonly SemaphoreSlim _semaphoreSlim = new(1, 1); private readonly IGameLanguageService _gameLanguage; private readonly IInvitationManager _invitationManager; private readonly IItemsManager _itemsManager; private readonly IRaidManager _raidManager; private readonly ISessionManager _sessionManager; public RaidPartyJoinEventHandler(IGameLanguageService gameLanguage, ISessionManager sessionManager, IInvitationManager invitationManager, IRaidManager raidManager, IItemsManager itemsManager) { _gameLanguage = gameLanguage; _sessionManager = sessionManager; _invitationManager = invitationManager; _raidManager = raidManager; _itemsManager = itemsManager; } public async Task HandleAsync(RaidPartyJoinEvent e, CancellationToken cancellation) { IClientSession session = e.Sender; long raidOwnerId = e.RaidOwnerId; bool isByRaidList = e.IsByRaidList; await _semaphoreSlim.WaitAsync(cancellation); try { if (session.PlayerEntity.Id == raidOwnerId) { return; } if (session.IsMuted()) { session.SendMsg(session.GetLanguage(GameDialogKey.MUTE_SHOUTMESSAGE_YOU_ARE_MUTED), MsgMessageType.Middle); return; } IClientSession raidOwner = _sessionManager.GetSessionByCharacterId(raidOwnerId); if (raidOwner?.PlayerEntity.Raid == null) { Log.Debug($"[ERROR] Character with ID {raidOwnerId.ToString()} was not found."); return; } if (session.PlayerEntity.IsBlocking(raidOwnerId)) { session.SendInfo(session.GetLanguage(GameDialogKey.BLACKLIST_INFO_BLOCKING)); return; } if (raidOwner.PlayerEntity.IsBlocking(session.PlayerEntity.Id)) { session.SendInfo(session.GetLanguage(GameDialogKey.BLACKLIST_INFO_BLOCKED)); return; } if (raidOwner.PlayerEntity.HasRaidStarted) { session.SendChatMessage(_gameLanguage.GetLanguage(GameDialogKey.RAID_CHATMESSAGE_NO_EXIST_OR_ALREADY_STARTED, session.UserLanguage), ChatMessageColorType.Yellow); return; } if (!_invitationManager.ContainsPendingInvitation(raidOwnerId, session.PlayerEntity.Id, InvitationType.Raid) && !isByRaidList) { Log.Debug($"[ERROR] Character with ID {session.PlayerEntity.Id.ToString()} to join a raid, but hadn't an invitation."); return; } if (!isByRaidList) { _invitationManager.RemovePendingInvitation(raidOwnerId, session.PlayerEntity.Id, InvitationType.Raid); } RaidParty raidParty = raidOwner.PlayerEntity.Raid; if (isByRaidList && !_raidManager.ContainsRaidInRaidPublishList(raidParty)) { session.SendInfo(_gameLanguage.GetLanguage(GameDialogKey.RAID_CHATMESSAGE_NO_EXIST_OR_ALREADY_STARTED, session.UserLanguage)); await session.EmitEventAsync(new RaidListOpenEvent()); return; } if (!session.CurrentMapInstance.HasMapFlag(MapFlags.IS_BASE_MAP)) { session.SendMsg(_gameLanguage.GetLanguage(GameDialogKey.INFORMATION_SHOUTMESSAGE_MUST_BE_IN_CLASSIC_MAP, session.UserLanguage), MsgMessageType.Middle); return; } if (raidOwner.PlayerEntity.RaidTeamIsFull) { session.SendMsg(_gameLanguage.GetLanguage(GameDialogKey.RAID_SHOUTMESSAGE_RAID_TEAM_FULL, session.UserLanguage), MsgMessageType.Middle); return; } if (session.PlayerEntity.IsInRaidParty) { session.SendMsg(_gameLanguage.GetLanguage(GameDialogKey.RAID_SHOUTMESSAGE_ALREADY_IN_RAID, session.UserLanguage), MsgMessageType.Middle); return; } if (session.PlayerEntity.TimeSpaceComponent.IsInTimeSpaceParty) { return; } if (session.PlayerEntity.RainbowBattleComponent.IsInRainbowBattle) { return; } if (session.PlayerEntity.HasRaidStarted || session.PlayerEntity.HasShopOpened) { return; } if (session.PlayerEntity.IsInGroup()) { session.SendMsg(_gameLanguage.GetLanguage(GameDialogKey.RAID_SHOUTMESSAGE_IN_GROUP, session.UserLanguage), MsgMessageType.Middle); return; } if (session.PlayerEntity.Level < raidParty.MinimumLevel) { session.SendChatMessage(_gameLanguage.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_LOW_LEVEL, session.UserLanguage, raidParty.MinimumLevel.ToString()), ChatMessageColorType.Red); return; } if (session.PlayerEntity.HeroLevel < raidParty.MinimumHeroLevel) { session.SendChatMessage(_gameLanguage.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_LOW_LEVEL, session.UserLanguage, raidParty.MinimumHeroLevel.ToString()), ChatMessageColorType.Red); return; } if (session.IsRaidTypeRestricted(raidParty.Type)) { if (!session.IsPlayerWearingRaidAmulet(raidParty.Type)) { string amuletName = raidParty.Type == RaidType.LordDraco ? _itemsManager.GetItem((short)ItemVnums.DRACO_AMULET)?.GetItemName(_gameLanguage, session.UserLanguage) : _itemsManager.GetItem((short)ItemVnums.GLACERUS_AMULET)?.GetItemName(_gameLanguage, session.UserLanguage); session.SendChatMessage(session.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_AMULET_NEEDED, amuletName), ChatMessageColorType.Yellow); return; } string getRaidName = session.GenerateRaidName(_gameLanguage, raidParty.Type); if (!session.CanPlayerJoinToRestrictedRaid(raidParty.Type)) { session.SendChatMessage(session.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_LIMIT_REACHED, getRaidName), ChatMessageColorType.Yellow); return; } switch (raidParty.Type) { case RaidType.LordDraco: session.SendChatMessage(session.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_LIMIT_LEFT, getRaidName, session.PlayerEntity.RaidRestrictionDto.LordDraco), ChatMessageColorType.Yellow); break; case RaidType.Glacerus: session.SendChatMessage(session.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_LIMIT_LEFT, getRaidName, session.PlayerEntity.RaidRestrictionDto.Glacerus), ChatMessageColorType.Yellow); break; } } if (session.PlayerEntity.Level > raidParty.MaximumLevel || session.PlayerEntity.HeroLevel > raidParty.MaximumHeroLevel) { session.SendChatMessage(_gameLanguage.GetLanguage(GameDialogKey.RAID_CHATMESSAGE_LEVEL_TOO_HIGH, session.UserLanguage), ChatMessageColorType.Yellow); } raidParty.AddMember(session); session.PlayerEntity.SetRaidParty(raidParty); raidOwner.SendRaidPacket(RaidPacketType.LIST_MEMBERS); foreach (IClientSession member in session.PlayerEntity.Raid.Members) { member.SendChatMessage(_gameLanguage.GetLanguageFormat(GameDialogKey.RAID_CHATMESSAGE_X_JOINED, member.UserLanguage, session.PlayerEntity.Name), ChatMessageColorType.Yellow); member.SendMsg(_gameLanguage.GetLanguageFormat(GameDialogKey.RAID_SHOUTMESSAGE_X_JOINED, member.UserLanguage, session.PlayerEntity.Name), MsgMessageType.Middle); member.RefreshRaidMemberList(); } session.SendRaidPacket(RaidPacketType.LEAVE); session.SendRaidPacket(RaidPacketType.LEADER_RELATED); await session.EmitEventAsync(new RaidJoinedEvent { JoinType = e.IsByRaidList ? RaidJoinType.RAID_LIST : RaidJoinType.INVITATION }); } finally { _semaphoreSlim.Release(); } } }