diff --git a/Source/Framework/Constants/BattleGroundsConst.cs b/Source/Framework/Constants/BattleGroundsConst.cs index ea7002a06..6fcf7c7b0 100644 --- a/Source/Framework/Constants/BattleGroundsConst.cs +++ b/Source/Framework/Constants/BattleGroundsConst.cs @@ -134,25 +134,8 @@ namespace Framework.Constants // 809 = "New Nagrand Arena (Legion)" AF = 816, // Ashamane'S Fall // 844 = "New Blade'S Edge Arena (Legion)" - Max = 845 - } - - public enum BattlegroundQueueTypeId - { - None = 0, - AV = 1, - WS = 2, - AB = 3, - EY = 4, - SA = 5, - IC = 6, - TP = 7, - BFG = 8, - RB = 9, - Arena2v2 = 10, - Arena3v3 = 11, - Arena5v5 = 12, - Max + RandomEpic = 901, + Max = 902 } public enum BattlegroundQueueIdType diff --git a/Source/Framework/Constants/Network/Opcodes.cs b/Source/Framework/Constants/Network/Opcodes.cs index 6ad3971e3..eb7c8aea8 100644 --- a/Source/Framework/Constants/Network/Opcodes.cs +++ b/Source/Framework/Constants/Network/Opcodes.cs @@ -799,8 +799,6 @@ namespace Framework.Constants AreaTriggerRePath = 0x263f, AreaTriggerReShape = 0x2644, ArenaCrowdControlSpells = 0x2652, - ArenaMatchEnd = 0x28a7, - ArenaMatchStart = 0x28a6, ArenaPrepOpponentSpecializations = 0x2668, ArtifactForgeOpened = 0x27e8, ArtifactRespecConfirm = 0x27eb, @@ -1517,7 +1515,9 @@ namespace Framework.Constants PushSpellToActionBar = 0x2c51, PvpCredit = 0x271f, PvpLogData = 0x25b4, - PvpMatchStart = 0x28ac, + PvpMatchEnd = 0x28a7, + PvpMatchInit = 0x28ac, + PvpMatchStart = 0x28a6, PvpOptionsEnabled = 0x25b7, PvpSeason = 0x25d4, QueryBattlePetNameResponse = 0x270e, diff --git a/Source/Framework/Constants/PlayerConst.cs b/Source/Framework/Constants/PlayerConst.cs index 2a40ffb9f..f0c6f3e63 100644 --- a/Source/Framework/Constants/PlayerConst.cs +++ b/Source/Framework/Constants/PlayerConst.cs @@ -472,7 +472,7 @@ namespace Framework.Constants InvisibilityGlow = 0x40 } - public enum AreaTeams + public enum ArenaTeams { None = 0, Ally = 2, diff --git a/Source/Game/BattleGrounds/BattleGround.cs b/Source/Game/BattleGrounds/BattleGround.cs index 0cdd325ec..960b6d4da 100644 --- a/Source/Game/BattleGrounds/BattleGround.cs +++ b/Source/Game/BattleGrounds/BattleGround.cs @@ -415,14 +415,6 @@ namespace Game.BattleGrounds Player player = Global.ObjAccessor.FindPlayer(guid); if (player) { - // BG Status packet - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); - uint queueSlot = player.GetBattlegroundQueueIndex(bgQueueTypeId); - - BattlefieldStatusActive battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, this, player, queueSlot, player.GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player.SendPacket(battlefieldStatus); - // Correctly display EnemyUnitFrame player.SetArenaFaction((byte)player.GetBGTeam()); @@ -699,10 +691,12 @@ namespace Game.BattleGrounds //we must set it this way, because end time is sent in packet! SetRemainingTime(BattlegroundConst.AutocloseBattleground); - PVPLogData pvpLogData; - BuildPvPLogDataPacket(out pvpLogData); - - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + PVPMatchEnd pvpMatchEnd = new PVPMatchEnd(); + pvpMatchEnd.Winner = (byte)GetWinner(); + pvpMatchEnd.Duration = (int)Math.Max(0, (GetElapsedTime() - (int)BattlegroundStartTimeIntervals.Delay2m) / Time.InMilliseconds); + pvpMatchEnd.LogData.HasValue = true; + BuildPvPLogDataPacket(out pvpMatchEnd.LogData.Value); + pvpMatchEnd.Write(); foreach (var pair in m_Players) { @@ -799,11 +793,7 @@ namespace Game.BattleGrounds BlockMovement(player); - player.SendPacket(pvpLogData); - - BattlefieldStatusActive battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, this, player, player.GetBattlegroundQueueIndex(bgQueueTypeId), player.GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player.SendPacket(battlefieldStatus); + player.SendPacket(pvpMatchEnd); player.UpdateCriteria(CriteriaTypes.CompleteBattleground, player.GetMapId()); } @@ -866,7 +856,7 @@ namespace Game.BattleGrounds RemovePlayer(player, guid, team); // BG subclass specific code BattlegroundTypeId bgTypeId = GetTypeID(); - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = GetQueueId(); if (participant) // if the player was a match participant, remove auras, calc rating, update queue { @@ -907,7 +897,7 @@ namespace Game.BattleGrounds { // a player has left the Battleground, so there are free slots . add to queue AddToBGFreeSlotQueue(); - Global.BattlegroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, GetBracketId()); + Global.BattlegroundMgr.ScheduleQueueUpdate(0, bgQueueTypeId, GetBracketId()); } // Let others know BattlegroundPlayerLeft playerLeft = new BattlegroundPlayerLeft(); @@ -1006,13 +996,36 @@ namespace Game.BattleGrounds playerJoined.Guid = player.GetGUID(); SendPacketToTeam(team, playerJoined, player); - // BG Status packet - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); - uint queueSlot = player.GetBattlegroundQueueIndex(bgQueueTypeId); + PVPMatchInit pvpMatchState = new PVPMatchInit(); + pvpMatchState.MapID = GetMapId(); + switch (GetStatus()) + { + case BattlegroundStatus.None: + case BattlegroundStatus.WaitQueue: + pvpMatchState.State = PVPMatchInit.MatchState.Inactive; + break; + case BattlegroundStatus.WaitJoin: + case BattlegroundStatus.InProgress: + pvpMatchState.State = PVPMatchInit.MatchState.InProgress; + break; + case BattlegroundStatus.WaitLeave: + pvpMatchState.State = PVPMatchInit.MatchState.Complete; + break; + default: + break; + } - BattlefieldStatusActive battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, this, player, queueSlot, player.GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player.SendPacket(battlefieldStatus); + if (GetElapsedTime() >= (int)BattlegroundStartTimeIntervals.Delay2m) + { + pvpMatchState.Duration = (int)(GetElapsedTime() - (int)BattlegroundStartTimeIntervals.Delay2m) / Time.InMilliseconds; + pvpMatchState.StartTime = GameTime.GetGameTime() - pvpMatchState.Duration; + } + pvpMatchState.ArenaFaction = (byte)(player.GetBGTeam() == Team.Horde ? BattlegroundTeamId.Horde : BattlegroundTeamId.Alliance); + pvpMatchState.BattlemasterListID = (uint)GetTypeID(); + pvpMatchState.Registered = false; + pvpMatchState.AffectsRating = IsRated(); + + player.SendPacket(pvpMatchState); player.RemoveAurasByType(AuraType.Mounted); @@ -1132,7 +1145,7 @@ namespace Game.BattleGrounds { if (!m_InBGFreeSlotQueue && IsBattleground()) { - Global.BattlegroundMgr.AddToBGFreeSlotQueue(GetTypeID(), this); + Global.BattlegroundMgr.AddToBGFreeSlotQueue(GetQueueId(), this); m_InBGFreeSlotQueue = true; } } @@ -1142,7 +1155,7 @@ namespace Game.BattleGrounds { if (m_InBGFreeSlotQueue) { - Global.BattlegroundMgr.RemoveFromBGFreeSlotQueue(GetTypeID(), m_InstanceID); + Global.BattlegroundMgr.RemoveFromBGFreeSlotQueue(GetQueueId(), m_InstanceID); m_InBGFreeSlotQueue = false; } } @@ -1415,7 +1428,7 @@ namespace Game.BattleGrounds public uint GetMapId() { - return _battlegroundTemplate.BattlemasterEntry.MapId[0]; + return (uint)_battlegroundTemplate.BattlemasterEntry.MapId[0]; } public void SpawnBGObject(int type, uint respawntime) @@ -1692,17 +1705,11 @@ namespace Game.BattleGrounds if (GetStatus() != BattlegroundStatus.WaitLeave) return; - PVPLogData pvpLogData; - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); - BlockMovement(player); - BuildPvPLogDataPacket(out pvpLogData); + PVPLogDataMessage pvpLogData = new PVPLogDataMessage(); + BuildPvPLogDataPacket(out pvpLogData.Data); player.SendPacket(pvpLogData); - - BattlefieldStatusActive battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, this, player, player.GetBattlegroundQueueIndex(bgQueueTypeId), player.GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player.SendPacket(battlefieldStatus); } public uint GetAlivePlayersCountByTeam(Team Team) @@ -1801,15 +1808,6 @@ namespace Game.BattleGrounds return _battlegroundTemplate.BattlemasterEntry.Name[Global.WorldMgr.GetDefaultDbcLocale()]; } - public ulong GetQueueId() - { - BattlegroundQueueIdType type = BattlegroundQueueIdType.Battleground; - if (IsArena()) - type = IsRated() ? BattlegroundQueueIdType.Arena : BattlegroundQueueIdType.ArenaSkirmish; - - return (ulong)_battlegroundTemplate.Id | (ulong)type << 16 | 0x1F10000000000000; - } - public BattlegroundTypeId GetTypeID(bool getRandom = false) { return getRandom ? m_RandomTypeID : _battlegroundTemplate.Id; @@ -1883,6 +1881,7 @@ namespace Game.BattleGrounds public virtual void DestroyGate(Player player, GameObject go) { } public virtual bool IsAllNodesControlledByTeam(Team team) { return false; } + public BattlegroundQueueTypeId GetQueueId() { return m_queueId; } public uint GetInstanceID() { return m_InstanceID; } public BattlegroundStatus GetStatus() { return m_Status; } public uint GetClientInstanceID() { return m_ClientInstanceID; } @@ -1895,6 +1894,7 @@ namespace Game.BattleGrounds BattlegroundTeamId GetWinner() { return _winnerTeamId; } public bool IsRandom() { return m_IsRandom; } + public void SetQueueId(BattlegroundQueueTypeId queueId) { m_queueId = queueId; } public void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; } //here we can count minlevel and maxlevel for players public void SetInstanceID(uint InstanceID) { m_InstanceID = InstanceID; } @@ -2032,6 +2032,7 @@ namespace Game.BattleGrounds public uint[] Buff_Entries = { BattlegroundConst.SpeedBuff, BattlegroundConst.RegenBuff, BattlegroundConst.BerserkerBuff }; // Battleground + BattlegroundQueueTypeId m_queueId; BattlegroundTypeId m_RandomTypeID; uint m_InstanceID; // Battleground Instance's GUID! BattlegroundStatus m_Status; diff --git a/Source/Game/BattleGrounds/BattleGroundManager.cs b/Source/Game/BattleGrounds/BattleGroundManager.cs index 299a1583d..a4d766dda 100644 --- a/Source/Game/BattleGrounds/BattleGroundManager.cs +++ b/Source/Game/BattleGrounds/BattleGroundManager.cs @@ -33,20 +33,20 @@ namespace Game.BattleGrounds BattlegroundManager() { m_NextRatedArenaUpdate = WorldConfig.GetUIntValue(WorldCfg.ArenaRatedUpdateTimer); - - for (var i = 0; i < (int)BattlegroundQueueTypeId.Max; ++i) - m_BattlegroundQueues[i] = new BattlegroundQueue(); } public void DeleteAllBattlegrounds() { - foreach (var data in bgDataStore.Values) - { - data.m_Battlegrounds.Clear(); - data.BGFreeSlotQueue.Clear(); - } + foreach (var data in bgDataStore.Values.ToList()) + while(data.m_Battlegrounds.Empty()) + data.m_Battlegrounds.First().Value.Dispose(); bgDataStore.Clear(); + + foreach (var bg in m_BGFreeSlotQueue.Values.ToList()) + bg.Dispose(); + + m_BGFreeSlotQueue.Clear(); } public void Update(uint diff) @@ -79,23 +79,21 @@ namespace Game.BattleGrounds m_UpdateTimer = 0; } // update events timer - for (var qtype = BattlegroundQueueTypeId.None; qtype < BattlegroundQueueTypeId.Max; ++qtype) - m_BattlegroundQueues[(int)qtype].UpdateEvents(diff); + foreach (var pair in m_BattlegroundQueues) + pair.Value.UpdateEvents(diff); // update scheduled queues if (!m_QueueUpdateScheduler.Empty()) { - List scheduled = new List(); + List scheduled = new List(); Extensions.Swap(ref scheduled, ref m_QueueUpdateScheduler); for (byte i = 0; i < scheduled.Count; i++) { - uint arenaMMRating = (uint)(scheduled[i] >> 32); - byte arenaType = (byte)(scheduled[i] >> 24 & 255); - BattlegroundQueueTypeId bgQueueTypeId = (BattlegroundQueueTypeId)(scheduled[i] >> 16 & 255); - BattlegroundTypeId bgTypeId = (BattlegroundTypeId)((scheduled[i] >> 8) & 255); - BattlegroundBracketId bracket_id = (BattlegroundBracketId)(scheduled[i] & 255); - m_BattlegroundQueues[(int)bgQueueTypeId].BattlegroundQueueUpdate(diff, bgTypeId, bracket_id, arenaType, arenaMMRating > 0, arenaMMRating); + uint arenaMMRating = scheduled[i].ArenaMatchmakerRating; + BattlegroundQueueTypeId bgQueueTypeId = scheduled[i].QueueId; + BattlegroundBracketId bracket_id = scheduled[i].BracketId; + GetBattlegroundQueue(bgQueueTypeId).BattlegroundQueueUpdate(diff, bracket_id, arenaMMRating); } } @@ -107,14 +105,11 @@ namespace Game.BattleGrounds { // forced update for rated arenas (scan all, but skipped non rated) Log.outDebug(LogFilter.Arena, "BattlegroundMgr: UPDATING ARENA QUEUES"); - for (var qtype = BattlegroundQueueTypeId.Arena2v2; qtype <= BattlegroundQueueTypeId.Arena5v5; ++qtype) + foreach (ArenaTypes teamSize in new[] { ArenaTypes.Team2v2, ArenaTypes.Team3v3, ArenaTypes.Team5v5 }) { - for (int bracket = (int)BattlegroundBracketId.First; bracket < (int)BattlegroundBracketId.Max; ++bracket) - { - m_BattlegroundQueues[(int)qtype].BattlegroundQueueUpdate(diff, - BattlegroundTypeId.AA, (BattlegroundBracketId)bracket, - (byte)BGArenaType(qtype), true, 0); - } + BattlegroundQueueTypeId ratedArenaQueueId = BGQueueTypeId((ushort)BattlegroundTypeId.AA, BattlegroundQueueIdType.Arena, true, teamSize); + for (var bracket = BattlegroundBracketId.First; bracket < BattlegroundBracketId.Max; ++bracket) + GetBattlegroundQueue(ratedArenaQueueId).BattlegroundQueueUpdate(diff, bracket, 0); } m_NextRatedArenaUpdate = WorldConfig.GetUIntValue(WorldCfg.ArenaRatedUpdateTimer); @@ -124,14 +119,14 @@ namespace Game.BattleGrounds } } - void BuildBattlegroundStatusHeader(BattlefieldStatusHeader header, Battleground bg, Player player, uint ticketId, uint joinTime, ArenaTypes arenaType) + void BuildBattlegroundStatusHeader(BattlefieldStatusHeader header, Battleground bg, Player player, uint ticketId, uint joinTime, BattlegroundQueueTypeId queueId, ArenaTypes arenaType) { header.Ticket = new RideTicket(); header.Ticket.RequesterGuid = player.GetGUID(); header.Ticket.Id = ticketId; header.Ticket.Type = RideType.Battlegrounds; header.Ticket.Time = (int)joinTime; - header.QueueID.Add(bg.GetQueueId()); + header.QueueID.Add(queueId.GetPacked()); header.RangeMin = (byte)bg.GetMinLevel(); header.RangeMax = (byte)bg.GetMaxLevel(); header.TeamSize = (byte)(bg.IsArena() ? arenaType : 0); @@ -152,7 +147,7 @@ namespace Game.BattleGrounds public void BuildBattlegroundStatusNeedConfirmation(out BattlefieldStatusNeedConfirmation battlefieldStatus, Battleground bg, Player player, uint ticketId, uint joinTime, uint timeout, ArenaTypes arenaType) { battlefieldStatus = new BattlefieldStatusNeedConfirmation(); - BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, arenaType); + BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, bg.GetQueueId(), arenaType); battlefieldStatus.Mapid = bg.GetMapId(); battlefieldStatus.Timeout = timeout; battlefieldStatus.Role = 0; @@ -161,7 +156,7 @@ namespace Game.BattleGrounds public void BuildBattlegroundStatusActive(out BattlefieldStatusActive battlefieldStatus, Battleground bg, Player player, uint ticketId, uint joinTime, ArenaTypes arenaType) { battlefieldStatus = new BattlefieldStatusActive(); - BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, arenaType); + BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, bg.GetQueueId(), arenaType); battlefieldStatus.ShutdownTimer = bg.GetRemainingTime(); battlefieldStatus.ArenaFaction = (byte)(player.GetBGTeam() == Team.Horde ? TeamId.Horde : TeamId.Alliance); battlefieldStatus.LeftEarly = false; @@ -169,10 +164,10 @@ namespace Game.BattleGrounds battlefieldStatus.Mapid = bg.GetMapId(); } - public void BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatus, Battleground bg, Player player, uint ticketId, uint joinTime, uint avgWaitTime, ArenaTypes arenaType, bool asGroup) + public void BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatus, Battleground bg, Player player, uint ticketId, uint joinTime, BattlegroundQueueTypeId queueId, uint avgWaitTime, ArenaTypes arenaType, bool asGroup) { battlefieldStatus = new BattlefieldStatusQueued(); - BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, arenaType); + BuildBattlegroundStatusHeader(battlefieldStatus.Hdr, bg, player, ticketId, joinTime, queueId, arenaType); battlefieldStatus.AverageWaitTime = avgWaitTime; battlefieldStatus.AsGroup = asGroup; battlefieldStatus.SuspendedQueue = false; @@ -180,14 +175,14 @@ namespace Game.BattleGrounds battlefieldStatus.WaitTime = Time.GetMSTimeDiffToNow(joinTime); } - public void BuildBattlegroundStatusFailed(out BattlefieldStatusFailed battlefieldStatus, Battleground bg, Player pPlayer, uint ticketId, ArenaTypes arenaType, GroupJoinBattlegroundResult result, ObjectGuid errorGuid = default) + public void BuildBattlegroundStatusFailed(out BattlefieldStatusFailed battlefieldStatus, Battleground bg, Player pPlayer, uint ticketId, GroupJoinBattlegroundResult result, ObjectGuid errorGuid = default) { battlefieldStatus = new BattlefieldStatusFailed(); battlefieldStatus.Ticket.RequesterGuid = pPlayer.GetGUID(); battlefieldStatus.Ticket.Id = ticketId; battlefieldStatus.Ticket.Type = RideType.Battlegrounds; - battlefieldStatus.Ticket.Time = (int)pPlayer.GetBattlegroundQueueJoinTime(BGQueueTypeId(bg.GetTypeID(), arenaType)); - battlefieldStatus.QueueID = bg.GetQueueId(); + battlefieldStatus.Ticket.Time = (int)pPlayer.GetBattlegroundQueueJoinTime(bg.GetQueueId()); + battlefieldStatus.QueueID = bg.GetQueueId().GetPacked(); battlefieldStatus.Reason = (int)result; if (!errorGuid.IsEmpty() && (result == GroupJoinBattlegroundResult.NotInBattleground || result == GroupJoinBattlegroundResult.JoinTimedOut)) battlefieldStatus.ClientID = errorGuid; @@ -198,7 +193,7 @@ namespace Game.BattleGrounds if (instanceId == 0) return null; - if (bgTypeId != BattlegroundTypeId.None) + if (bgTypeId != BattlegroundTypeId.None || bgTypeId == BattlegroundTypeId.RB || bgTypeId == BattlegroundTypeId.RandomEpic) { var data = bgDataStore.LookupByKey(bgTypeId); return data.m_Battlegrounds.LookupByKey(instanceId); @@ -249,9 +244,9 @@ namespace Game.BattleGrounds } // create a new Battleground that will really be used to play - public Battleground CreateNewBattleground(BattlegroundTypeId originalBgTypeId, PvpDifficultyRecord bracketEntry, ArenaTypes arenaType, bool isRated) + public Battleground CreateNewBattleground(BattlegroundQueueTypeId queueId, PvpDifficultyRecord bracketEntry) { - BattlegroundTypeId bgTypeId = GetRandomBG(originalBgTypeId); + BattlegroundTypeId bgTypeId = GetRandomBG((BattlegroundTypeId)queueId.BattlemasterListId); // get the template BG Battleground bg_template = GetBattlegroundTemplate(bgTypeId); @@ -261,22 +256,23 @@ namespace Game.BattleGrounds return null; } - if (bgTypeId == BattlegroundTypeId.RB || bgTypeId == BattlegroundTypeId.AA) + if (bgTypeId == BattlegroundTypeId.RB || bgTypeId == BattlegroundTypeId.AA || bgTypeId == BattlegroundTypeId.RandomEpic) return null; // create a copy of the BG template Battleground bg = bg_template.GetCopy(); - bool isRandom = bgTypeId != originalBgTypeId && !bg.IsArena(); + bool isRandom = bgTypeId != (BattlegroundTypeId)queueId.BattlemasterListId && !bg.IsArena(); + bg.SetQueueId(queueId); bg.SetBracket(bracketEntry); bg.SetInstanceID(Global.MapMgr.GenerateInstanceId()); - bg.SetClientInstanceID(CreateClientVisibleInstanceId(isRandom ? BattlegroundTypeId.RB : bgTypeId, bracketEntry.GetBracketId())); + bg.SetClientInstanceID(CreateClientVisibleInstanceId((BattlegroundTypeId)queueId.BattlemasterListId, bracketEntry.GetBracketId())); bg.Reset(); // reset the new bg (set status to status_wait_queue from status_none) bg.SetStatus(BattlegroundStatus.WaitJoin); // start the joining of the bg - bg.SetArenaType(arenaType); + bg.SetArenaType((ArenaTypes)queueId.TeamSize); bg.SetRandomTypeID(bgTypeId); - bg.SetRated(isRated); + bg.SetRated(queueId.Rated); bg.SetRandom(isRandom); return bg; @@ -339,13 +335,15 @@ namespace Game.BattleGrounds bg = new BattlegroundBFG(bgTemplate); break; */ + case BattlegroundTypeId.RandomEpic: + bg = new Battleground(bgTemplate); + bg.SetRandom(true); + break; default: return false; } } - bg.SetInstanceID(0); - if (!bgDataStore.ContainsKey(bg.GetTypeID())) bgDataStore[bg.GetTypeID()] = new BattlegroundData(); @@ -390,7 +388,7 @@ namespace Game.BattleGrounds bgTemplate.ScriptId = Global.ObjectMgr.GetScriptId(result.Read(5)); bgTemplate.BattlemasterEntry = bl; - if (bgTemplate.Id != BattlegroundTypeId.AA && bgTemplate.Id != BattlegroundTypeId.RB) + if (bgTemplate.Id != BattlegroundTypeId.AA && bgTemplate.Id != BattlegroundTypeId.RB && bgTemplate.Id != BattlegroundTypeId.RandomEpic) { uint startId = result.Read(1); WorldSafeLocsEntry start = Global.ObjectMgr.GetWorldSafeLoc(startId); @@ -486,94 +484,9 @@ namespace Game.BattleGrounds || bgTypeId == BattlegroundTypeId.DS || bgTypeId == BattlegroundTypeId.RV || bgTypeId == BattlegroundTypeId.RL; } - public BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, ArenaTypes arenaType) + public BattlegroundQueueTypeId BGQueueTypeId(ushort battlemasterListId, BattlegroundQueueIdType type, bool rated, ArenaTypes teamSize) { - switch (bgTypeId) - { - case BattlegroundTypeId.AB: - return BattlegroundQueueTypeId.AB; - case BattlegroundTypeId.AV: - return BattlegroundQueueTypeId.AV; - case BattlegroundTypeId.EY: - return BattlegroundQueueTypeId.EY; - case BattlegroundTypeId.IC: - return BattlegroundQueueTypeId.IC; - case BattlegroundTypeId.TP: - return BattlegroundQueueTypeId.TP; - case BattlegroundTypeId.BFG: - return BattlegroundQueueTypeId.BFG; - case BattlegroundTypeId.RB: - return BattlegroundQueueTypeId.RB; - case BattlegroundTypeId.SA: - return BattlegroundQueueTypeId.SA; - case BattlegroundTypeId.WS: - return BattlegroundQueueTypeId.WS; - case BattlegroundTypeId.AA: - case BattlegroundTypeId.BE: - case BattlegroundTypeId.DS: - case BattlegroundTypeId.NA: - case BattlegroundTypeId.RL: - case BattlegroundTypeId.RV: - switch (arenaType) - { - case ArenaTypes.Team2v2: - return BattlegroundQueueTypeId.Arena2v2; - case ArenaTypes.Team3v3: - return BattlegroundQueueTypeId.Arena3v3; - case ArenaTypes.Team5v5: - return BattlegroundQueueTypeId.Arena5v5; - default: - return BattlegroundQueueTypeId.None; - } - default: - return BattlegroundQueueTypeId.None; - } - } - - public BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId) - { - switch (bgQueueTypeId) - { - case BattlegroundQueueTypeId.WS: - return BattlegroundTypeId.WS; - case BattlegroundQueueTypeId.AB: - return BattlegroundTypeId.AB; - case BattlegroundQueueTypeId.AV: - return BattlegroundTypeId.AV; - case BattlegroundQueueTypeId.EY: - return BattlegroundTypeId.EY; - case BattlegroundQueueTypeId.SA: - return BattlegroundTypeId.SA; - case BattlegroundQueueTypeId.IC: - return BattlegroundTypeId.IC; - case BattlegroundQueueTypeId.TP: - return BattlegroundTypeId.TP; - case BattlegroundQueueTypeId.BFG: - return BattlegroundTypeId.BFG; - case BattlegroundQueueTypeId.RB: - return BattlegroundTypeId.RB; - case BattlegroundQueueTypeId.Arena2v2: - case BattlegroundQueueTypeId.Arena3v3: - case BattlegroundQueueTypeId.Arena5v5: - return BattlegroundTypeId.AA; - default: - return 0; // used for unknown template (it existed and do nothing) - } - } - - public ArenaTypes BGArenaType(BattlegroundQueueTypeId bgQueueTypeId) - { - switch (bgQueueTypeId) - { - case BattlegroundQueueTypeId.Arena2v2: - return ArenaTypes.Team2v2; - case BattlegroundQueueTypeId.Arena3v3: - return ArenaTypes.Team3v3; - case BattlegroundQueueTypeId.Arena5v5: - return ArenaTypes.Team5v5; - default: - return 0; - } + return new BattlegroundQueueTypeId(battlemasterListId, (byte)type, rated, (byte)teamSize); } public void ToggleTesting() @@ -599,10 +512,51 @@ namespace Game.BattleGrounds } } - public void ScheduleQueueUpdate(uint arenaMatchmakerRating, ArenaTypes arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id) + public bool IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId) + { + BattlemasterListRecord battlemasterList = CliDB.BattlemasterListStorage.LookupByKey(bgQueueTypeId.BattlemasterListId); + if (battlemasterList == null) + return false; + + switch ((BattlegroundQueueIdType)bgQueueTypeId.BgType) + { + case BattlegroundQueueIdType.Battleground: + if (battlemasterList.InstanceType != (int)MapTypes.Battleground) + return false; + if (bgQueueTypeId.TeamSize != 0) + return false; + break; + case BattlegroundQueueIdType.Arena: + if (battlemasterList.InstanceType != (int)MapTypes.Arena) + return false; + if (!bgQueueTypeId.Rated) + return false; + if (bgQueueTypeId.TeamSize == 0) + return false; + break; + case BattlegroundQueueIdType.Wargame: + if (bgQueueTypeId.Rated) + return false; + break; + case BattlegroundQueueIdType.ArenaSkirmish: + if (battlemasterList.InstanceType != (int)MapTypes.Arena) + return false; + if (bgQueueTypeId.Rated) + return false; + if (bgQueueTypeId.TeamSize != 0) + return false; + break; + default: + return false; + } + + return true; + } + + public void ScheduleQueueUpdate(uint arenaMatchmakerRating, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id) { //we will use only 1 number created of bgTypeId and bracket_id - ulong scheduleId = ((ulong)arenaMatchmakerRating << 32) | ((uint)arenaType << 24) | ((uint)bgQueueTypeId << 16) | ((uint)bgTypeId << 8) | (uint)bracket_id; + ScheduledQueueUpdate scheduleId = new ScheduledQueueUpdate(arenaMatchmakerRating, bgQueueTypeId, bracket_id); if (!m_QueueUpdateScheduler.Contains(scheduleId)) m_QueueUpdateScheduler.Add(scheduleId); } @@ -766,19 +720,19 @@ namespace Game.BattleGrounds return BattlegroundTypeId.None; } - public List GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId) + public List GetBGFreeSlotQueueStore(BattlegroundQueueTypeId bgTypeId) { - return bgDataStore[bgTypeId].BGFreeSlotQueue; + return m_BGFreeSlotQueue[bgTypeId]; } - public void AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground bg) + public void AddToBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, Battleground bg) { - bgDataStore[bgTypeId].BGFreeSlotQueue.Insert(0, bg); + m_BGFreeSlotQueue.Add(bgTypeId, bg); } - public void RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint instanceId) + public void RemoveFromBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, uint instanceId) { - var queues = bgDataStore[bgTypeId].BGFreeSlotQueue; + var queues = m_BGFreeSlotQueue[bgTypeId]; foreach (var bg in queues) { if (bg.GetInstanceID() == instanceId) @@ -800,7 +754,13 @@ namespace Game.BattleGrounds bgDataStore[bgTypeId].m_Battlegrounds.Remove(instanceId); } - public BattlegroundQueue GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[(int)bgQueueTypeId]; } + public BattlegroundQueue GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) + { + if (!m_BattlegroundQueues.ContainsKey(bgQueueTypeId)) + m_BattlegroundQueues[bgQueueTypeId] = new BattlegroundQueue(bgQueueTypeId); + + return m_BattlegroundQueues[bgQueueTypeId]; + } public bool IsArenaTesting() { return m_ArenaTesting; } public bool IsTesting() { return m_Testing; } @@ -821,11 +781,46 @@ namespace Game.BattleGrounds } Dictionary bgDataStore = new Dictionary(); - BattlegroundQueue[] m_BattlegroundQueues = new BattlegroundQueue[(int)BattlegroundQueueTypeId.Max]; + Dictionary m_BattlegroundQueues = new Dictionary(); + MultiMap m_BGFreeSlotQueue = new MultiMap(); Dictionary mBattleMastersMap = new Dictionary(); Dictionary _battlegroundTemplates = new Dictionary(); Dictionary _battlegroundMapTemplates = new Dictionary(); - List m_QueueUpdateScheduler = new List(); + + struct ScheduledQueueUpdate + { + public ScheduledQueueUpdate(uint arenaMatchmakerRating, BattlegroundQueueTypeId queueId, BattlegroundBracketId bracketId) + { + ArenaMatchmakerRating = arenaMatchmakerRating; + QueueId = queueId; + BracketId = bracketId; + } + + public uint ArenaMatchmakerRating; + public BattlegroundQueueTypeId QueueId; + public BattlegroundBracketId BracketId; + + public static bool operator ==(ScheduledQueueUpdate right, ScheduledQueueUpdate left) + { + return left.ArenaMatchmakerRating == right.ArenaMatchmakerRating && left.QueueId == right.QueueId && left.BracketId == right.BracketId; + } + + public static bool operator !=(ScheduledQueueUpdate right, ScheduledQueueUpdate left) + { + return !(right == left); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public override int GetHashCode() + { + return ArenaMatchmakerRating.GetHashCode() ^ QueueId.GetHashCode() ^ BracketId.GetHashCode(); + } + } + List m_QueueUpdateScheduler = new List(); uint m_NextRatedArenaUpdate; uint m_UpdateTimer; bool m_ArenaTesting; @@ -842,7 +837,6 @@ namespace Game.BattleGrounds public Dictionary m_Battlegrounds = new Dictionary(); public List[] m_ClientBattlegroundIds = new List[(int)BattlegroundBracketId.Max]; - public List BGFreeSlotQueue = new List(); public Battleground Template; } diff --git a/Source/Game/BattleGrounds/BattleGroundQueue.cs b/Source/Game/BattleGrounds/BattleGroundQueue.cs index c7f3fdf8e..422434a1d 100644 --- a/Source/Game/BattleGrounds/BattleGroundQueue.cs +++ b/Source/Game/BattleGrounds/BattleGroundQueue.cs @@ -30,8 +30,10 @@ namespace Game.BattleGrounds { public class BattlegroundQueue { - public BattlegroundQueue() + public BattlegroundQueue(BattlegroundQueueTypeId queueId) { + m_queueId = queueId; + for (var i = 0; i < (int)BattlegroundBracketId.Max; ++i) { m_QueuedGroups[i] = new List[BattlegroundConst.BgQueueTypesCount]; @@ -329,14 +331,13 @@ namespace Game.BattleGrounds Player plr2 = Global.ObjAccessor.FindConnectedPlayer(group.Players.FirstOrDefault().Key); if (plr2) { - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(group.BgTypeId, group.ArenaType); - uint queueSlot = plr2.GetBattlegroundQueueIndex(bgQueueTypeId); + uint queueSlot = plr2.GetBattlegroundQueueIndex(m_queueId); - plr2.RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to + plr2.RemoveBattlegroundQueueId(m_queueId); // must be called this way, because if you move this call to // queue.removeplayer, it causes bugs BattlefieldStatusNone battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusNone(out battlefieldStatus, plr2, queueSlot, plr2.GetBattlegroundQueueJoinTime(bgQueueTypeId)); + Global.BattlegroundMgr.BuildBattlegroundStatusNone(out battlefieldStatus, plr2, queueSlot, plr2.GetBattlegroundQueueJoinTime(m_queueId)); plr2.SendPacket(battlefieldStatus); } // then actually delete, this may delete the group as well! @@ -381,7 +382,7 @@ namespace Game.BattleGrounds // set invitation ginfo.IsInvitedToBGInstanceGUID = bg.GetInstanceID(); BattlegroundTypeId bgTypeId = bg.GetTypeID(); - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(bgTypeId, bg.GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = bg.GetQueueId(); BattlegroundBracketId bracket_id = bg.GetBracketId(); // set ArenaTeamId for rated matches @@ -411,7 +412,7 @@ namespace Game.BattleGrounds BGQueueInviteEvent inviteEvent = new BGQueueInviteEvent(player.GetGUID(), ginfo.IsInvitedToBGInstanceGUID, bgTypeId, ginfo.ArenaType, ginfo.RemoveInviteTime); m_events.AddEvent(inviteEvent, m_events.CalculateTime(BattlegroundConst.InvitationRemindTime)); // create automatic remove events - BGQueueRemoveEvent removeEvent = new BGQueueRemoveEvent(player.GetGUID(), ginfo.IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo.RemoveInviteTime); + BGQueueRemoveEvent removeEvent = new BGQueueRemoveEvent(player.GetGUID(), ginfo.IsInvitedToBGInstanceGUID, bgQueueTypeId, ginfo.RemoveInviteTime); m_events.AddEvent(removeEvent, m_events.CalculateTime(BattlegroundConst.InviteAcceptWaitTime)); uint queueSlot = player.GetBattlegroundQueueIndex(bgQueueTypeId); @@ -730,7 +731,7 @@ namespace Game.BattleGrounds /// /// /// - public void BattlegroundQueueUpdate(uint diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, byte arenaType, bool isRated, uint arenaRating) + public void BattlegroundQueueUpdate(uint diff, BattlegroundBracketId bracket_id, uint arenaRating) { //if no players in queue - do nothing if (m_QueuedGroups[(int)bracket_id][BattlegroundConst.BgQueuePremadeAlliance].Empty() && @@ -741,11 +742,11 @@ namespace Game.BattleGrounds // Battleground with free slot for player should be always in the beggining of the queue // maybe it would be better to create bgfreeslotqueue for each bracket_id - var bgQueues = Global.BattlegroundMgr.GetBGFreeSlotQueueStore(bgTypeId); + var bgQueues = Global.BattlegroundMgr.GetBGFreeSlotQueueStore(m_queueId); foreach (var bg in bgQueues) { // DO NOT allow queue manager to invite new player to rated games - if (!bg.IsRated() && bg.GetTypeID() == bgTypeId && bg.GetBracketId() == bracket_id && + if (!bg.IsRated() && bg.GetBracketId() == bracket_id && bg.GetStatus() > BattlegroundStatus.WaitQueue && bg.GetStatus() < BattlegroundStatus.WaitLeave) { // clear selection pools @@ -769,10 +770,10 @@ namespace Game.BattleGrounds // finished iterating through the bgs with free slots, maybe we need to create a new bg - Battleground bg_template = Global.BattlegroundMgr.GetBattlegroundTemplate(bgTypeId); + Battleground bg_template = Global.BattlegroundMgr.GetBattlegroundTemplate((BattlegroundTypeId)m_queueId.BattlemasterListId); if (!bg_template) { - Log.outError(LogFilter.Battleground, "Battleground: Update: bg template not found for {0}", bgTypeId); + Log.outError(LogFilter.Battleground, $"Battleground: Update: bg template not found for {m_queueId.BattlemasterListId}"); return; } @@ -789,8 +790,8 @@ namespace Game.BattleGrounds if (bg_template.IsArena()) { - MaxPlayersPerTeam = arenaType; - MinPlayersPerTeam = (uint)(Global.BattlegroundMgr.IsArenaTesting() ? 1 : arenaType); + MaxPlayersPerTeam = m_queueId.TeamSize; + MinPlayersPerTeam = Global.BattlegroundMgr.IsArenaTesting() ? 1u : m_queueId.TeamSize; } else if (Global.BattlegroundMgr.IsTesting()) MinPlayersPerTeam = 1; @@ -803,10 +804,10 @@ namespace Game.BattleGrounds if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)) { // create new Battleground - Battleground bg2 = Global.BattlegroundMgr.CreateNewBattleground(bgTypeId, bracketEntry, 0, false); + Battleground bg2 = Global.BattlegroundMgr.CreateNewBattleground(m_queueId, bracketEntry); if (bg2 == null) { - Log.outError(LogFilter.Battleground, "BattlegroundQueue.Update - Cannot create Battleground: {0}", bgTypeId); + Log.outError(LogFilter.Battleground, $"BattlegroundQueue.Update - Cannot create Battleground: {m_queueId.BattlemasterListId}"); return; } // invite those selection pools @@ -822,17 +823,17 @@ namespace Game.BattleGrounds } // now check if there are in queues enough players to start new game of (normal Battleground, or non-rated arena) - if (!isRated) + if (!m_queueId.Rated) { // if there are enough players in pools, start new Battleground or non rated arena if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam) || (bg_template.IsArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam))) { // we successfully created a pool - Battleground bg2 = Global.BattlegroundMgr.CreateNewBattleground(bgTypeId, bracketEntry, (ArenaTypes)arenaType, false); + Battleground bg2 = Global.BattlegroundMgr.CreateNewBattleground(m_queueId, bracketEntry); if (bg2 == null) { - Log.outError(LogFilter.Battleground, "BattlegroundQueue.Update - Cannot create Battleground: {0}", bgTypeId); + Log.outError(LogFilter.Battleground, $"BattlegroundQueue.Update - Cannot create Battleground: {m_queueId.BattlemasterListId}"); return; } @@ -928,7 +929,7 @@ namespace Game.BattleGrounds { GroupQueueInfo aTeam = queueArray[TeamId.Alliance]; GroupQueueInfo hTeam = queueArray[TeamId.Horde]; - Battleground arena = Global.BattlegroundMgr.CreateNewBattleground(bgTypeId, bracketEntry, (ArenaTypes)arenaType, true); + Battleground arena = Global.BattlegroundMgr.CreateNewBattleground(m_queueId, bracketEntry); if (!arena) { Log.outError(LogFilter.Battleground, "BattlegroundQueue.Update couldn't create arena instance for rated arena match!"); @@ -965,6 +966,8 @@ namespace Game.BattleGrounds } } + BattlegroundQueueTypeId m_queueId; + Dictionary m_QueuedPlayers = new Dictionary(); /// @@ -1046,6 +1049,85 @@ namespace Game.BattleGrounds } + public struct BattlegroundQueueTypeId + { + public ushort BattlemasterListId; + public byte BgType; + public bool Rated; + public byte TeamSize; + + public BattlegroundQueueTypeId(ushort battlemasterListId, byte bgType, bool rated, byte teamSize) + { + BattlemasterListId = battlemasterListId; + BgType = bgType; + Rated = rated; + TeamSize = teamSize; + } + + public static BattlegroundQueueTypeId FromPacked(ulong packedQueueId) + { + return new BattlegroundQueueTypeId((ushort)(packedQueueId & 0xFFFF), (byte)((packedQueueId >> 16) & 0xF), ((packedQueueId >> 20) & 1) != 0, (byte)((packedQueueId >> 24) & 0x3F)); + } + + public ulong GetPacked() + { + return (ulong)BattlemasterListId + | ((ulong)(BgType & 0xF) << 16) + | ((ulong)(Rated ? 1 : 0) << 20) + | ((ulong)(TeamSize & 0x3F) << 24) + | 0x1F10000000000000; + } + + public static bool operator ==(BattlegroundQueueTypeId left, BattlegroundQueueTypeId right) + { + return left.BattlemasterListId == right.BattlemasterListId + && left.BgType == right.BgType + && left.Rated == right.Rated + && left.TeamSize == right.TeamSize; + } + + public static bool operator !=(BattlegroundQueueTypeId left, BattlegroundQueueTypeId right) + { + return !(left == right); + } + + public static bool operator <(BattlegroundQueueTypeId left, BattlegroundQueueTypeId right) + { + if (left.BattlemasterListId != right.BattlemasterListId) + return left.BattlemasterListId < right.BattlemasterListId; + if (left.BgType != right.BgType) + return left.BgType < right.BgType; + if (left.Rated != right.Rated) + return (left.Rated ? 1 : 0) < (right.Rated ? 1 : 0); + return left.TeamSize < right.TeamSize; + } + public static bool operator >(BattlegroundQueueTypeId left, BattlegroundQueueTypeId right) + { + if (left.BattlemasterListId != right.BattlemasterListId) + return left.BattlemasterListId > right.BattlemasterListId; + if (left.BgType != right.BgType) + return left.BgType > right.BgType; + if (left.Rated != right.Rated) + return (left.Rated ? 1 : 0) > (right.Rated ? 1 : 0); + return left.TeamSize > right.TeamSize; + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public override int GetHashCode() + { + return BattlemasterListId.GetHashCode() ^ BgType.GetHashCode() ^ Rated.GetHashCode() ^ TeamSize.GetHashCode(); + } + + public override string ToString() + { + return $"{{ BattlemasterListId: {BattlemasterListId}, Type: {BgType}, Rated: {Rated}, TeamSize: {TeamSize} }}"; + } + } + /// /// stores information for players in queue /// @@ -1081,11 +1163,11 @@ namespace Game.BattleGrounds /// class BGQueueInviteEvent : BasicEvent { - public BGQueueInviteEvent(ObjectGuid pl_guid, uint BgInstanceGUID, BattlegroundTypeId BgTypeId, ArenaTypes arenaType, uint removeTime) + public BGQueueInviteEvent(ObjectGuid plGuid, uint bgInstanceGUID, BattlegroundTypeId bgTypeId, ArenaTypes arenaType, uint removeTime) { - m_PlayerGuid = pl_guid; - m_BgInstanceGUID = BgInstanceGUID; - m_BgTypeId = BgTypeId; + m_PlayerGuid = plGuid; + m_BgInstanceGUID = bgInstanceGUID; + m_BgTypeId = bgTypeId; m_ArenaType = arenaType; m_RemoveTime = removeTime; } @@ -1102,7 +1184,7 @@ namespace Game.BattleGrounds if (bg == null) return true; - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(bg.GetTypeID(), bg.GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = bg.GetQueueId(); uint queueSlot = player.GetBattlegroundQueueIndex(bgQueueTypeId); if (queueSlot < SharedConst.BGTeamsCount) // player is in queue or in Battleground { @@ -1134,12 +1216,11 @@ namespace Game.BattleGrounds /// class BGQueueRemoveEvent : BasicEvent { - public BGQueueRemoveEvent(ObjectGuid pl_guid, uint bgInstanceGUID, BattlegroundTypeId BgTypeId, BattlegroundQueueTypeId bgQueueTypeId, uint removeTime) + public BGQueueRemoveEvent(ObjectGuid plGuid, uint bgInstanceGUID, BattlegroundQueueTypeId bgQueueTypeId, uint removeTime) { - m_PlayerGuid = pl_guid; + m_PlayerGuid = plGuid; m_BgInstanceGUID = bgInstanceGUID; m_RemoveTime = removeTime; - m_BgTypeId = BgTypeId; m_BgQueueTypeId = bgQueueTypeId; } @@ -1150,7 +1231,7 @@ namespace Game.BattleGrounds // player logged off (we should do nothing, he is correctly removed from queue in another procedure) return true; - Battleground bg = Global.BattlegroundMgr.GetBattleground(m_BgInstanceGUID, m_BgTypeId); + Battleground bg = Global.BattlegroundMgr.GetBattleground(m_BgInstanceGUID, (BattlegroundTypeId)m_BgQueueTypeId.BattlemasterListId); //Battleground can be deleted already when we are removing queue info //bg pointer can be NULL! so use it carefully! @@ -1167,7 +1248,7 @@ namespace Game.BattleGrounds bgQueue.RemovePlayer(m_PlayerGuid, true); //update queues if Battleground isn't ended if (bg && bg.IsBattleground() && bg.GetStatus() != BattlegroundStatus.WaitLeave) - Global.BattlegroundMgr.ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg.GetBracketId()); + Global.BattlegroundMgr.ScheduleQueueUpdate(0, m_BgQueueTypeId, bg.GetBracketId()); BattlefieldStatusNone battlefieldStatus; Global.BattlegroundMgr.BuildBattlegroundStatusNone(out battlefieldStatus, player, queueSlot, player.GetBattlegroundQueueJoinTime(m_BgQueueTypeId)); @@ -1184,7 +1265,6 @@ namespace Game.BattleGrounds ObjectGuid m_PlayerGuid; uint m_BgInstanceGUID; uint m_RemoveTime; - BattlegroundTypeId m_BgTypeId; BattlegroundQueueTypeId m_BgQueueTypeId; } } diff --git a/Source/Game/DataStorage/Structs/B_Records.cs b/Source/Game/DataStorage/Structs/B_Records.cs index e9543601c..d8e42d043 100644 --- a/Source/Game/DataStorage/Structs/B_Records.cs +++ b/Source/Game/DataStorage/Structs/B_Records.cs @@ -101,7 +101,7 @@ namespace Game.DataStorage public BattlemasterListFlags Flags; public int IconFileDataID; public short RequiredPlayerConditionID; - public ushort[] MapId = new ushort[16]; + public short[] MapId = new short[16]; } public sealed class BroadcastTextRecord diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index cf252ce07..e10e64846 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -881,7 +881,7 @@ namespace Game.Entities if (questBit != 0) SetQuestCompletedBit(questBit, true); - Log.outDebug(LogFilter.Player, "Weekly quest {{0}} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString()); + Log.outDebug(LogFilter.Player, "Weekly quest {0} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString()); } while (result.NextRow()); } @@ -907,7 +907,7 @@ namespace Game.Entities if (questBit != 0) SetQuestCompletedBit(questBit, true); - Log.outDebug(LogFilter.Player, "Seasonal quest {{0}} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString()); + Log.outDebug(LogFilter.Player, "Seasonal quest {0} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString()); } while (result.NextRow()); } @@ -936,7 +936,7 @@ namespace Game.Entities if (questBit != 0) SetQuestCompletedBit(questBit, true); - Log.outDebug(LogFilter.Player, "Monthly quest {{0}} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString()); + Log.outDebug(LogFilter.Player, "Monthly quest {0} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString()); } while (result.NextRow()); } @@ -2600,7 +2600,7 @@ namespace Game.Entities { map = currentBg.GetBgMap(); - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(currentBg.GetTypeID(), currentBg.GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = currentBg.GetQueueId(); AddBattlegroundQueueId(bgQueueTypeId); m_bgData.bgTypeID = currentBg.GetTypeID(); diff --git a/Source/Game/Entities/Player/Player.Fields.cs b/Source/Game/Entities/Player/Player.Fields.cs index f8e8e6fa7..cbf76201e 100644 --- a/Source/Game/Entities/Player/Player.Fields.cs +++ b/Source/Game/Entities/Player/Player.Fields.cs @@ -27,6 +27,7 @@ using Game.Misc; using Game.Spells; using System.Collections; using System.Collections.Generic; +using Game.BattleGrounds; namespace Game.Entities { diff --git a/Source/Game/Entities/Player/Player.Map.cs b/Source/Game/Entities/Player/Player.Map.cs index e4a8bd5ac..c39bbf151 100644 --- a/Source/Game/Entities/Player/Player.Map.cs +++ b/Source/Game/Entities/Player/Player.Map.cs @@ -188,15 +188,15 @@ namespace Game.Entities // in PvP, any not controlled zone (except zone.team == 6, default case) // in PvE, only opposition team capital - switch ((AreaTeams)zone.FactionGroupMask) + switch ((ArenaTeams)zone.FactionGroupMask) { - case AreaTeams.Ally: + case ArenaTeams.Ally: pvpInfo.IsInHostileArea = GetTeam() != Team.Alliance && (Global.WorldMgr.IsPvPRealm() || zone.Flags[0].HasAnyFlag(AreaFlags.Capital)); break; - case AreaTeams.Horde: + case ArenaTeams.Horde: pvpInfo.IsInHostileArea = GetTeam() != Team.Horde && (Global.WorldMgr.IsPvPRealm() || zone.Flags[0].HasAnyFlag(AreaFlags.Capital)); break; - case AreaTeams.None: + case ArenaTeams.None: // overwrite for Battlegrounds, maybe batter some zone flags but current known not 100% fit to this pvpInfo.IsInHostileArea = Global.WorldMgr.IsPvPRealm() || InBattleground() || zone.Flags[0].HasAnyFlag(AreaFlags.Wintergrasp); break; diff --git a/Source/Game/Entities/Player/Player.PvP.cs b/Source/Game/Entities/Player/Player.PvP.cs index 63d7897f8..b45bc0595 100644 --- a/Source/Game/Entities/Player/Player.PvP.cs +++ b/Source/Game/Entities/Player/Player.PvP.cs @@ -534,7 +534,7 @@ namespace Game.Entities public bool InBattlegroundQueue() { for (byte i = 0; i < SharedConst.MaxPlayerBGQueues; ++i) - if (m_bgBattlegroundQueueID[i].bgQueueTypeId != BattlegroundQueueTypeId.None) + if (m_bgBattlegroundQueueID[i].bgQueueTypeId != default) return true; return false; } @@ -544,7 +544,7 @@ namespace Game.Entities if (index < SharedConst.MaxPlayerBGQueues) return m_bgBattlegroundQueueID[index].bgQueueTypeId; - return BattlegroundQueueTypeId.None; + return default; } public uint GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) @@ -578,11 +578,11 @@ namespace Game.Entities { for (byte i = 0; i < SharedConst.MaxPlayerBGQueues; ++i) { - if (m_bgBattlegroundQueueID[i].bgQueueTypeId == BattlegroundQueueTypeId.None || m_bgBattlegroundQueueID[i].bgQueueTypeId == val) + if (m_bgBattlegroundQueueID[i].bgQueueTypeId == default || m_bgBattlegroundQueueID[i].bgQueueTypeId == val) { m_bgBattlegroundQueueID[i].bgQueueTypeId = val; m_bgBattlegroundQueueID[i].invitedToInstance = 0; - m_bgBattlegroundQueueID[i].joinTime = Time.GetMSTime(); + m_bgBattlegroundQueueID[i].joinTime = (uint)GameTime.GetGameTime(); return i; } } @@ -592,7 +592,7 @@ namespace Game.Entities public bool HasFreeBattlegroundQueueId() { for (byte i = 0; i < SharedConst.MaxPlayerBGQueues; ++i) - if (m_bgBattlegroundQueueID[i].bgQueueTypeId == BattlegroundQueueTypeId.None) + if (m_bgBattlegroundQueueID[i].bgQueueTypeId == default) return true; return false; } @@ -603,7 +603,7 @@ namespace Game.Entities { if (m_bgBattlegroundQueueID[i].bgQueueTypeId == val) { - m_bgBattlegroundQueueID[i].bgQueueTypeId = BattlegroundQueueTypeId.None; + m_bgBattlegroundQueueID[i].bgQueueTypeId = default; m_bgBattlegroundQueueID[i].invitedToInstance = 0; m_bgBattlegroundQueueID[i].joinTime = 0; return; diff --git a/Source/Game/Groups/Group.cs b/Source/Game/Groups/Group.cs index 82e0829df..c2800422f 100644 --- a/Source/Game/Groups/Group.cs +++ b/Source/Game/Groups/Group.cs @@ -1736,8 +1736,6 @@ namespace Game.Groups uint arenaTeamId = reference.GetArenaTeamId((byte)arenaSlot); Team team = reference.GetTeam(); - BattlegroundQueueTypeId bgQueueTypeIdRandom = Global.BattlegroundMgr.BGQueueTypeId(BattlegroundTypeId.RB, 0); - // check every member of the group to be able to join memberscount = 0; for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next(), ++memberscount) @@ -1762,11 +1760,13 @@ namespace Game.Groups // don't let join if someone from the group is already in that bg queue if (member.InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId)) return GroupJoinBattlegroundResult.JoinFailed; // not blizz-like - // don't let join if someone from the group is in bg queue random - if (member.InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeIdRandom)) + // don't let join if someone from the group is in bg queue random + bool isInRandomBgQueue = member.InBattlegroundQueueForBattlegroundQueueType(Global.BattlegroundMgr.BGQueueTypeId((ushort)BattlegroundTypeId.RB, BattlegroundQueueIdType.Battleground, false, 0)) + || member.InBattlegroundQueueForBattlegroundQueueType(Global.BattlegroundMgr.BGQueueTypeId((ushort)BattlegroundTypeId.RandomEpic, BattlegroundQueueIdType.Battleground, false, 0)); + if (isInRandomBgQueue) return GroupJoinBattlegroundResult.InRandomBg; // don't let join to bg queue random if someone from the group is already in bg queue - if (bgOrTemplate.GetTypeID() == BattlegroundTypeId.RB && member.InBattlegroundQueue()) + if ((bgOrTemplate.GetTypeID() == BattlegroundTypeId.RB || bgOrTemplate.GetTypeID() == BattlegroundTypeId.RandomEpic) && member.InBattlegroundQueue() && !isInRandomBgQueue) return GroupJoinBattlegroundResult.InNonRandomBg; // check for deserter debuff in case not arena queue if (bgOrTemplate.GetTypeID() != BattlegroundTypeId.AA && !member.CanJoinToBattleground(bgOrTemplate)) diff --git a/Source/Game/Handlers/BattleGroundHandler.cs b/Source/Game/Handlers/BattleGroundHandler.cs index 3312dce7c..55c10699b 100644 --- a/Source/Game/Handlers/BattleGroundHandler.cs +++ b/Source/Game/Handlers/BattleGroundHandler.cs @@ -64,23 +64,21 @@ namespace Game return; } - BattlegroundTypeId bgTypeId = (BattlegroundTypeId)(battlemasterJoin.QueueIDs[0] & 0xFFFF); - BattlemasterListRecord battlemasterListEntry = CliDB.BattlemasterListStorage.LookupByKey(bgTypeId); - if (battlemasterListEntry == null) + BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId.FromPacked(battlemasterJoin.QueueIDs[0]); + if (!Global.BattlegroundMgr.IsValidQueueId(bgQueueTypeId)) { - Log.outError(LogFilter.Network, "Battleground: invalid bgtype ({0}) received. possible cheater? player guid {1}", bgTypeId, GetPlayer().GetGUID().ToString()); + Log.outError(LogFilter.Network, $"Battleground: invalid bg queue {bgQueueTypeId} received. possible cheater? {_player.GetGUID()}"); return; } - if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, (uint)bgTypeId, null) || battlemasterListEntry.Flags.HasAnyFlag(BattlemasterListFlags.Disabled)) + BattlemasterListRecord battlemasterListEntry = CliDB.BattlemasterListStorage.LookupByKey(bgQueueTypeId.BattlemasterListId); + if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, bgQueueTypeId.BattlemasterListId, null) || battlemasterListEntry.Flags.HasAnyFlag(BattlemasterListFlags.Disabled)) { GetPlayer().SendSysMessage(CypherStrings.BgDisabled); return; } - // can do this, since it's Battleground, not arena - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(bgTypeId, 0); - BattlegroundQueueTypeId bgQueueTypeIdRandom = Global.BattlegroundMgr.BGQueueTypeId(BattlegroundTypeId.RB, 0); + BattlegroundTypeId bgTypeId = (BattlegroundTypeId)bgQueueTypeId.BattlemasterListId; // ignore if player is already in BG if (GetPlayer().InBattleground()) @@ -106,7 +104,7 @@ namespace Game { if (GetPlayer().IsUsingLfg()) { - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.LfgCantUseBattleground); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.LfgCantUseBattleground); SendPacket(battlefieldStatusFailed); return; } @@ -114,23 +112,25 @@ namespace Game // check Deserter debuff if (!GetPlayer().CanJoinToBattleground(bg)) { - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.Deserters); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.Deserters); SendPacket(battlefieldStatusFailed); return; } - if (GetPlayer().GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < SharedConst.MaxPlayerBGQueues) + bool isInRandomBgQueue = _player.InBattlegroundQueueForBattlegroundQueueType(Global.BattlegroundMgr.BGQueueTypeId((ushort)BattlegroundTypeId.RB, BattlegroundQueueIdType.Battleground, false, 0)) + || _player.InBattlegroundQueueForBattlegroundQueueType(Global.BattlegroundMgr.BGQueueTypeId((ushort)BattlegroundTypeId.RandomEpic, BattlegroundQueueIdType.Battleground, false, 0)); + if (bgTypeId != BattlegroundTypeId.RB && bgTypeId != BattlegroundTypeId.RandomEpic && isInRandomBgQueue) { // player is already in random queue - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.InRandomBg); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.InRandomBg); SendPacket(battlefieldStatusFailed); return; } - if (GetPlayer().InBattlegroundQueue() && bgTypeId == BattlegroundTypeId.RB) + if (_player.InBattlegroundQueue() && !isInRandomBgQueue && (bgTypeId == BattlegroundTypeId.RB || bgTypeId == BattlegroundTypeId.RandomEpic)) { // player is already in queue, can't start random queue - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.InNonRandomBg); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.InNonRandomBg); SendPacket(battlefieldStatusFailed); return; } @@ -142,7 +142,7 @@ namespace Game // check if has free queue slots if (!GetPlayer().HasFreeBattlegroundQueueId()) { - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, 0, GroupJoinBattlegroundResult.TooManyQueues); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatusFailed, bg, GetPlayer(), 0, GroupJoinBattlegroundResult.TooManyQueues); SendPacket(battlefieldStatusFailed); return; } @@ -157,12 +157,10 @@ namespace Game uint avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId()); uint queueSlot = GetPlayer().AddBattlegroundQueueId(bgQueueTypeId); - BattlefieldStatusQueued battlefieldStatusQueued; - Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatusQueued, bg, GetPlayer(), queueSlot, ginfo.JoinTime, avgTime, ginfo.ArenaType, false); + Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatusQueued, bg, GetPlayer(), queueSlot, ginfo.JoinTime, bgQueueTypeId, avgTime, ginfo.ArenaType, false); SendPacket(battlefieldStatusQueued); - Log.outDebug(LogFilter.Battleground, "Battleground: player joined queue for bg queue type {0} bg type {1}: GUID {2}, NAME {3}", - bgQueueTypeId, bgTypeId, GetPlayer().GetGUID().ToString(), GetPlayer().GetName()); + Log.outDebug(LogFilter.Battleground, $"Battleground: player joined queue for bg queue {bgQueueTypeId}, {_player.GetGUID()}, NAME {_player.GetName()}"); } else { @@ -193,7 +191,7 @@ namespace Game if (err != 0) { BattlefieldStatusFailed battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, 0, err, errorGuid); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, err, errorGuid); member.SendPacket(battlefieldStatus); continue; } @@ -201,16 +199,14 @@ namespace Game // add to queue uint queueSlot = member.AddBattlegroundQueueId(bgQueueTypeId); - BattlefieldStatusQueued battlefieldStatusQueued; - Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, avgTime, ginfo.ArenaType, true); + Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, bgQueueTypeId, avgTime, ginfo.ArenaType, true); member.SendPacket(battlefieldStatusQueued); - Log.outDebug(LogFilter.Battleground, "Battleground: player joined queue for bg queue type {0} bg type {1}: GUID {2}, NAME {3}", - bgQueueTypeId, bgTypeId, member.GetGUID().ToString(), member.GetName()); + Log.outDebug(LogFilter.Battleground, $"Battleground: player joined queue for bg queue {bgQueueTypeId}, {member.GetGUID()}, NAME {member.GetName()}"); } Log.outDebug(LogFilter.Battleground, "Battleground: group end"); } - Global.BattlegroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry.GetBracketId()); + Global.BattlegroundMgr.ScheduleQueueUpdate(0, bgQueueTypeId, bracketEntry.GetBracketId()); } [WorldPacketHandler(ClientOpcodes.PvpLogData)] @@ -224,8 +220,8 @@ namespace Game if (bg.IsArena()) return; - PVPLogData pvpLogData; - bg.BuildPvPLogDataPacket(out pvpLogData); + PVPLogDataMessage pvpLogData = new PVPLogDataMessage(); + bg.BuildPvPLogDataPacket(out pvpLogData.Data); SendPacket(pvpLogData); } @@ -253,7 +249,7 @@ namespace Game } BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(battlefieldPort.Ticket.Id); - if (bgQueueTypeId == BattlegroundQueueTypeId.None) + if (bgQueueTypeId == default) { Log.outDebug(LogFilter.Battleground, "CMSG_BATTLEFIELD_PORT {0} Slot: {1}, Unk: {2}, Time: {3}, AcceptedInvite: {4}. Invalid queueSlot!", GetPlayerInfo(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, battlefieldPort.AcceptedInvite); @@ -278,7 +274,7 @@ namespace Game return; } - BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.BGTemplateId(bgQueueTypeId); + BattlegroundTypeId bgTypeId = (BattlegroundTypeId)bgQueueTypeId.BattlemasterListId; // BGTemplateId returns Battleground_AA when it is arena queue. // Do instance id search as there is no AA bg instances. Battleground bg = Global.BattlegroundMgr.GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BattlegroundTypeId.AA ? BattlegroundTypeId.None : bgTypeId); @@ -315,7 +311,7 @@ namespace Game { // send bg command result to show nice message BattlefieldStatusFailed battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), battlefieldPort.Ticket.Id, 0, GroupJoinBattlegroundResult.Deserters); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), battlefieldPort.Ticket.Id, GroupJoinBattlegroundResult.Deserters); SendPacket(battlefieldStatus); battlefieldPort.AcceptedInvite = false; Log.outDebug(LogFilter.Battleground, "Player {0} ({1}) has a deserter debuff, do not port him to Battleground!", GetPlayer().GetName(), GetPlayer().GetGUID().ToString()); @@ -372,7 +368,7 @@ namespace Game GetPlayer().SetBGTeam(ginfo.Team); Global.BattlegroundMgr.SendToBattleground(GetPlayer(), ginfo.IsInvitedToBGInstanceGUID, bgTypeId); - Log.outDebug(LogFilter.Battleground, "Battleground: player {0} ({1}) joined battle for bg {2}, bgtype {3}, queue type {4}.", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), bg.GetInstanceID(), bg.GetTypeID(), bgQueueTypeId); + Log.outDebug(LogFilter.Battleground, $"Battleground: player {_player.GetName()} ({_player.GetGUID()}) joined battle for bg {bg.GetInstanceID()}, bgtype {bg.GetTypeID()}, queue {bgQueueTypeId}."); } else // leave queue { @@ -395,9 +391,9 @@ namespace Game bgQueue.RemovePlayer(GetPlayer().GetGUID(), true); // player left queue, we should update it - do not update Arena Queue if (ginfo.ArenaType == 0) - Global.BattlegroundMgr.ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry.GetBracketId()); + Global.BattlegroundMgr.ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, bgQueueTypeId, bracketEntry.GetBracketId()); - Log.outDebug(LogFilter.Battleground, "Battleground: player {0} ({1}) left queue for bgtype {2}, queue type {3}.", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), bg.GetTypeID(), bgQueueTypeId); + Log.outDebug(LogFilter.Battleground, $"Battleground: player {_player.GetName()} ({_player.GetGUID()}) left queue for bgtype { bg.GetTypeID()}, queue {bgQueueTypeId}."); } } @@ -424,23 +420,19 @@ namespace Game for (byte i = 0; i < SharedConst.MaxPlayerBGQueues; ++i) { BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(i); - if (bgQueueTypeId == 0) + if (bgQueueTypeId == default) continue; - BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.BGTemplateId(bgQueueTypeId); - ArenaTypes arenaType = Global.BattlegroundMgr.BGArenaType(bgQueueTypeId); - if (bgTypeId == GetPlayer().GetBattlegroundTypeId()) + BattlegroundTypeId bgTypeId = (BattlegroundTypeId)bgQueueTypeId.BattlemasterListId; + ArenaTypes arenaType = (ArenaTypes)bgQueueTypeId.TeamSize; + bg = _player.GetBattleground(); + if (bg && bg.GetQueueId() == bgQueueTypeId) { - bg = GetPlayer().GetBattleground(); //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena //so i must use bg pointer to get that information - if (bg && bg.GetArenaType() == arenaType) - { - BattlefieldStatusActive battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusActive(out battlefieldStatus, bg, GetPlayer(), i, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), arenaType); - SendPacket(battlefieldStatus); - continue; - } + Global.BattlegroundMgr.BuildBattlegroundStatusActive(out BattlefieldStatusActive battlefieldStatus, bg, _player, i, _player.GetBattlegroundQueueJoinTime(bgQueueTypeId), arenaType); + SendPacket(battlefieldStatus); + continue; } //we are sending update to player about queue - he can be invited there! @@ -473,7 +465,7 @@ namespace Game uint avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId()); BattlefieldStatusQueued battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatus, bg, GetPlayer(), i, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), avgTime, arenaType, ginfo.Players.Count > 1); + Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatus, bg, GetPlayer(), i, GetPlayer().GetBattlegroundQueueJoinTime(bgQueueTypeId), bgQueueTypeId, avgTime, arenaType, ginfo.Players.Count > 1); SendPacket(battlefieldStatus); } } @@ -503,7 +495,7 @@ namespace Game } BattlegroundTypeId bgTypeId = bg.GetTypeID(); - BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId(bgTypeId, arenatype); + BattlegroundQueueTypeId bgQueueTypeId = Global.BattlegroundMgr.BGQueueTypeId((ushort)bgTypeId, BattlegroundQueueIdType.Arena, true, arenatype); PvpDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel(bg.GetMapId(), GetPlayer().GetLevel()); if (bracketEntry == null) return; @@ -553,7 +545,7 @@ namespace Game if (err != 0) { BattlefieldStatusFailed battlefieldStatus; - Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, arenatype, err, errorGuid); + Global.BattlegroundMgr.BuildBattlegroundStatusFailed(out battlefieldStatus, bg, GetPlayer(), 0, err, errorGuid); member.SendPacket(battlefieldStatus); continue; } @@ -561,14 +553,13 @@ namespace Game // add to queue uint queueSlot = member.AddBattlegroundQueueId(bgQueueTypeId); - BattlefieldStatusQueued battlefieldStatusQueued; - Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, avgTime, arenatype, true); + Global.BattlegroundMgr.BuildBattlegroundStatusQueued(out BattlefieldStatusQueued battlefieldStatusQueued, bg, member, queueSlot, ginfo.JoinTime, bgQueueTypeId, avgTime, arenatype, true); member.SendPacket(battlefieldStatusQueued); - Log.outDebug(LogFilter.Battleground, "Battleground: player joined queue for arena as group bg queue type {0} bg type {1}: GUID {2}, NAME {3}", bgQueueTypeId, bgTypeId, member.GetGUID().ToString(), member.GetName()); + Log.outDebug(LogFilter.Battleground, $"Battleground: player joined queue for arena as group bg queue {bgQueueTypeId}, {member.GetGUID()}, NAME {member.GetName()}"); } - Global.BattlegroundMgr.ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry.GetBracketId()); + Global.BattlegroundMgr.ScheduleQueueUpdate(matchmakerRating, bgQueueTypeId, bracketEntry.GetBracketId()); } [WorldPacketHandler(ClientOpcodes.ReportPvpPlayerAfk)] diff --git a/Source/Game/Handlers/MailHandler.cs b/Source/Game/Handlers/MailHandler.cs index 93524598b..841a1fae5 100644 --- a/Source/Game/Handlers/MailHandler.cs +++ b/Source/Game/Handlers/MailHandler.cs @@ -305,7 +305,7 @@ namespace Game if (log && packet.Info.SendMoney > 0) { - Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {{2}) mail money: {3} to player: {4} ({5}) (Account: {6})", + Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {2}) mail money: {3} to player: {4} ({5}) (Account: {6})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), packet.Info.SendMoney, packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } } diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 8e5da8d29..1e37f266b 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -420,9 +420,6 @@ namespace Game.Maps if (GridMaps[gx][gy] == null) { Map rootParentTerrainMap = m_parentMap.GetRootParentTerrainMap(); - // because LoadMapAndVMap is always entered using rootParentTerrainMap, we can only lock that once and not have to do it for every child map - if (this != rootParentTerrainMap) - Monitor.Enter(rootParentTerrainMap._gridLock); if (m_parentMap.GridMaps[gx][gy] == null) rootParentTerrainMap.LoadMapAndVMap(gx, gy); diff --git a/Source/Game/Network/Packets/BattleGroundPackets.cs b/Source/Game/Network/Packets/BattleGroundPackets.cs index 499bcd641..f698c2380 100644 --- a/Source/Game/Network/Packets/BattleGroundPackets.cs +++ b/Source/Game/Network/Packets/BattleGroundPackets.cs @@ -80,143 +80,16 @@ namespace Game.Network.Packets public override void Read() { } } - public class PVPLogData : ServerPacket + public class PVPLogDataMessage : ServerPacket { - public PVPLogData() : base(ServerOpcodes.PvpLogData, ConnectionType.Instance) { } + public PVPLogDataMessage() : base(ServerOpcodes.PvpLogData, ConnectionType.Instance) { } public override void Write() { - _worldPacket.WriteBit(Ratings.HasValue); - _worldPacket.WriteInt32(Statistics.Count); - foreach (var id in PlayerCount) - _worldPacket.WriteInt8(id); - - if (Ratings.HasValue) - Ratings.Value.Write(_worldPacket); - - foreach (PVPMatchPlayerStatistics player in Statistics) - player.Write(_worldPacket); + Data.Write(_worldPacket); } - public List Statistics = new List(); - public Optional Ratings; - public sbyte[] PlayerCount = new sbyte[2]; - - public class RatingData - { - public void Write(WorldPacket data) - { - foreach (var id in Prematch) - data.WriteUInt32(id); - - foreach (var id in Postmatch) - data.WriteUInt32(id); - - foreach (var id in PrematchMMR) - data.WriteUInt32(id); - } - - public uint[] Prematch = new uint[2]; - public uint[] Postmatch = new uint[2]; - public uint[] PrematchMMR = new uint[2]; - } - - public struct HonorData - { - public void Write(WorldPacket data) - { - data.WriteUInt32(HonorKills); - data.WriteUInt32(Deaths); - data.WriteUInt32(ContributionPoints); - } - - public uint HonorKills; - public uint Deaths; - public uint ContributionPoints; - } - - public struct PVPMatchPlayerPVPStat - { - public int PvpStatID; - public uint PvpStatValue; - - public PVPMatchPlayerPVPStat(int pvpStatID, uint pvpStatValue) - { - PvpStatID = pvpStatID; - PvpStatValue = pvpStatValue; - } - - public void Write(WorldPacket data) - { - data.WriteInt32(PvpStatID); - data.WriteUInt32(PvpStatValue); - } - - } - - public class PVPMatchPlayerStatistics - { - public void Write(WorldPacket data) - { - data.WritePackedGuid(PlayerGUID); - data.WriteUInt32(Kills); - data.WriteUInt32(DamageDone); - data.WriteUInt32(HealingDone); - data.WriteInt32(Stats.Count); - data.WriteInt32(PrimaryTalentTree); - data.WriteInt32(Sex); - data.WriteUInt32((uint)PlayerRace); - data.WriteInt32(PlayerClass); - data.WriteInt32(CreatureID); - data.WriteInt32(HonorLevel); - - foreach (var pvpStat in Stats) - pvpStat.Write(data); - - data.WriteBit(Faction); - data.WriteBit(IsInWorld); - data.WriteBit(Honor.HasValue); - data.WriteBit(PreMatchRating.HasValue); - data.WriteBit(RatingChange.HasValue); - data.WriteBit(PreMatchMMR.HasValue); - data.WriteBit(MmrChange.HasValue); - data.FlushBits(); - - if (Honor.HasValue) - Honor.Value.Write(data); - - if (PreMatchRating.HasValue) - data.WriteUInt32(PreMatchRating.Value); - - if (RatingChange.HasValue) - data.WriteInt32(RatingChange.Value); - - if (PreMatchMMR.HasValue) - data.WriteUInt32(PreMatchMMR.Value); - - if (MmrChange.HasValue) - data.WriteInt32(MmrChange.Value); - } - - public ObjectGuid PlayerGUID; - public uint Kills; - public byte Faction; - public bool IsInWorld; - public Optional Honor; - public uint DamageDone; - public uint HealingDone; - public Optional PreMatchRating; - public Optional RatingChange; - public Optional PreMatchMMR; - public Optional MmrChange; - public List Stats = new List(); - public int PrimaryTalentTree; - public int Sex; - public Race PlayerRace; - public int PlayerClass; - public int CreatureID; - public int HonorLevel; - } + public PVPLogData Data; } public class BattlefieldStatusNone : ServerPacket @@ -569,7 +442,198 @@ namespace Game.Network.Packets public override void Read() { } } + class PVPMatchInit : ServerPacket + { + public PVPMatchInit() : base(ServerOpcodes.PvpMatchInit, ConnectionType.Instance) { } + + public override void Write() + { + _worldPacket.WriteUInt32(MapID); + _worldPacket.WriteUInt8((byte)State); + _worldPacket.WriteInt32((int)StartTime); + _worldPacket.WriteInt32(Duration); + _worldPacket.WriteUInt8(ArenaFaction); + _worldPacket.WriteUInt32(BattlemasterListID); + _worldPacket.WriteBit(Registered); + _worldPacket.WriteBit(AffectsRating); + _worldPacket.FlushBits(); + } + + public enum MatchState + { + InProgress = 1, + Complete = 3, + Inactive = 4 + } + + public uint MapID; + public MatchState State = MatchState.Inactive; + public long StartTime; + public int Duration; + public byte ArenaFaction; + public uint BattlemasterListID; + public bool Registered; + public bool AffectsRating; + } + + class PVPMatchEnd : ServerPacket + { + public PVPMatchEnd() : base(ServerOpcodes.PvpMatchEnd, ConnectionType.Instance) { } + + public override void Write() + { + _worldPacket.WriteUInt8(Winner); + _worldPacket.WriteInt32(Duration); + _worldPacket.WriteBit(LogData.HasValue); + _worldPacket.FlushBits(); + + if (LogData.HasValue) + LogData.Value.Write(_worldPacket); + } + + public byte Winner; + public int Duration; + public Optional LogData; + } + //Structs + public class PVPLogData + { + public List Statistics = new List(); + public Optional Ratings; + public sbyte[] PlayerCount = new sbyte[2]; + + public class RatingData + { + public void Write(WorldPacket data) + { + foreach (var id in Prematch) + data.WriteUInt32(id); + + foreach (var id in Postmatch) + data.WriteUInt32(id); + + foreach (var id in PrematchMMR) + data.WriteUInt32(id); + } + + public uint[] Prematch = new uint[2]; + public uint[] Postmatch = new uint[2]; + public uint[] PrematchMMR = new uint[2]; + } + + public struct HonorData + { + public void Write(WorldPacket data) + { + data.WriteUInt32(HonorKills); + data.WriteUInt32(Deaths); + data.WriteUInt32(ContributionPoints); + } + + public uint HonorKills; + public uint Deaths; + public uint ContributionPoints; + } + + public struct PVPMatchPlayerPVPStat + { + public int PvpStatID; + public uint PvpStatValue; + + public PVPMatchPlayerPVPStat(int pvpStatID, uint pvpStatValue) + { + PvpStatID = pvpStatID; + PvpStatValue = pvpStatValue; + } + + public void Write(WorldPacket data) + { + data.WriteInt32(PvpStatID); + data.WriteUInt32(PvpStatValue); + } + + } + + public class PVPMatchPlayerStatistics + { + public void Write(WorldPacket data) + { + data.WritePackedGuid(PlayerGUID); + data.WriteUInt32(Kills); + data.WriteUInt32(DamageDone); + data.WriteUInt32(HealingDone); + data.WriteInt32(Stats.Count); + data.WriteInt32(PrimaryTalentTree); + data.WriteInt32(Sex); + data.WriteUInt32((uint)PlayerRace); + data.WriteInt32(PlayerClass); + data.WriteInt32(CreatureID); + data.WriteInt32(HonorLevel); + + foreach (var pvpStat in Stats) + pvpStat.Write(data); + + data.WriteBit(Faction); + data.WriteBit(IsInWorld); + data.WriteBit(Honor.HasValue); + data.WriteBit(PreMatchRating.HasValue); + data.WriteBit(RatingChange.HasValue); + data.WriteBit(PreMatchMMR.HasValue); + data.WriteBit(MmrChange.HasValue); + data.FlushBits(); + + if (Honor.HasValue) + Honor.Value.Write(data); + + if (PreMatchRating.HasValue) + data.WriteUInt32(PreMatchRating.Value); + + if (RatingChange.HasValue) + data.WriteInt32(RatingChange.Value); + + if (PreMatchMMR.HasValue) + data.WriteUInt32(PreMatchMMR.Value); + + if (MmrChange.HasValue) + data.WriteInt32(MmrChange.Value); + } + + public ObjectGuid PlayerGUID; + public uint Kills; + public byte Faction; + public bool IsInWorld; + public Optional Honor; + public uint DamageDone; + public uint HealingDone; + public Optional PreMatchRating; + public Optional RatingChange; + public Optional PreMatchMMR; + public Optional MmrChange; + public List Stats = new List(); + public int PrimaryTalentTree; + public int Sex; + public Race PlayerRace; + public int PlayerClass; + public int CreatureID; + public int HonorLevel; + } + + public void Write(WorldPacket data) + { + data.WriteBit(Ratings.HasValue); + data.WriteInt32(Statistics.Count); + foreach (var count in PlayerCount) + data.WriteInt8(count); + + if (Ratings.HasValue) + Ratings.Value.Write(data); + + foreach (var player in Statistics) + player.Write(data); + } + } + public class BattlefieldStatusHeader { public void Write(WorldPacket data) diff --git a/Source/Game/Server/WorldSession.cs b/Source/Game/Server/WorldSession.cs index 7dabf6bc1..4f6fe0e03 100644 --- a/Source/Game/Server/WorldSession.cs +++ b/Source/Game/Server/WorldSession.cs @@ -132,8 +132,8 @@ namespace Game for (uint i = 0; i < SharedConst.MaxPlayerBGQueues; ++i) { - BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(i); - if (bgQueueTypeId != 0) + BattlegroundQueueTypeId bgQueueTypeId = _player.GetBattlegroundQueueTypeId(i); + if (bgQueueTypeId != default) { _player.RemoveBattlegroundQueueId(bgQueueTypeId); BattlegroundQueue queue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);