From 7a9627a30b70b8d64ce43257b70698fbdc45a151 Mon Sep 17 00:00:00 2001 From: Baptiste Marie Date: Wed, 31 Jul 2024 05:24:37 +0200 Subject: [PATCH] Fix client crash caused by the server sending too many quests The server still allows the client to accept as many as it wants since auto-accept quests would be tricky to handle otherwise, but it will only send up to 25. If the client has accepted more than 25 and slots are freed, we move the quests that have too high of an index to these slots. --- GameServer/packets/Server/PacketLib168.cs | 48 ++++++++++++++++++++--- GameServer/packets/Server/PacketLib173.cs | 46 +++++++++++++++++++--- 2 files changed, 82 insertions(+), 12 deletions(-) diff --git a/GameServer/packets/Server/PacketLib168.cs b/GameServer/packets/Server/PacketLib168.cs index 470fb8b81d..fea12b6682 100644 --- a/GameServer/packets/Server/PacketLib168.cs +++ b/GameServer/packets/Server/PacketLib168.cs @@ -1539,18 +1539,54 @@ static CheckLosResponseHandler.TimeoutTimer CreateTimer((ushort sourceObjectId, public virtual void SendQuestListUpdate() { - HashSet sentIndexes = new(); + // Send up to 25 quests. + byte questIndex; + HashSet sentIndexes = []; + HashSet questsWithTooHighIndex = null; foreach (var entry in m_gameClient.Player.QuestList) { - SendQuestPacket(entry.Key, entry.Value); - sentIndexes.Add(entry.Value); + questIndex = entry.Value; + + if (questIndex < 25) + { + SendQuestPacket(entry.Key, questIndex); + sentIndexes.Add(questIndex); + } + else + { + if (questsWithTooHighIndex == null) + questsWithTooHighIndex = []; + + questsWithTooHighIndex.Add(entry.Key); + } + } + + // If possible, move and send quests which indexes are too high. + if (questsWithTooHighIndex != null) + { + questIndex = 0; + + foreach (AbstractQuest questWithTooHighIndex in questsWithTooHighIndex) + { + for ( ; questIndex < 25; questIndex++) + { + if (sentIndexes.Contains(questIndex)) + continue; + + m_gameClient.Player.QuestList[questWithTooHighIndex] = questIndex; + SendQuestPacket(questWithTooHighIndex, questIndex); + sentIndexes.Add(questIndex); + break; + } + } } - for (byte i = 0; i < 25; i++) + // Send null for unused indexes. + for (questIndex = 0; questIndex < 25; questIndex++) { - if (!sentIndexes.Contains(i)) - SendQuestPacket(null, i); + if (!sentIndexes.Contains(questIndex)) + SendQuestPacket(null, questIndex); } } diff --git a/GameServer/packets/Server/PacketLib173.cs b/GameServer/packets/Server/PacketLib173.cs index a52ea878f3..04a17f27ed 100644 --- a/GameServer/packets/Server/PacketLib173.cs +++ b/GameServer/packets/Server/PacketLib173.cs @@ -543,19 +543,53 @@ public override void SendQuestListUpdate() SendTaskInfo(); byte questIndex; - HashSet sentIndexes = new(); + HashSet sentIndexes = []; + HashSet questsWithTooHighIndex = null; + // Send up to 25 quests. foreach (var entry in m_gameClient.Player.QuestList) { questIndex = (byte) (entry.Value + 1); - SendQuestPacket(entry.Key, questIndex); - sentIndexes.Add(questIndex); + + if (questIndex < 26) + { + SendQuestPacket(entry.Key, questIndex); + sentIndexes.Add(questIndex); + } + else + { + if (questsWithTooHighIndex == null) + questsWithTooHighIndex = []; + + questsWithTooHighIndex.Add(entry.Key); + } + } + + // If possible, move and send quests which indexes are too high. + if (questsWithTooHighIndex != null) + { + questIndex = 1; + + foreach (AbstractQuest questWithTooHighIndex in questsWithTooHighIndex) + { + for ( ; questIndex < 26; questIndex++) + { + if (sentIndexes.Contains(questIndex)) + continue; + + m_gameClient.Player.QuestList[questWithTooHighIndex] = questIndex; + SendQuestPacket(questWithTooHighIndex, questIndex); + sentIndexes.Add(questIndex); + break; + } + } } - for (byte i = 1; i < 26; i++) + // Send null for unused indexes. + for (questIndex = 1; questIndex < 26; questIndex++) { - if (!sentIndexes.Contains(i)) - SendQuestPacket(null, i); + if (!sentIndexes.Contains(questIndex)) + SendQuestPacket(null, questIndex); } }