Browse Source

Validate network data when importing quest deltas

pull/7987/head
staphen 10 months ago committed by Stephen C. Wills
parent
commit
b761d3fef2
  1. 2
      Source/CMakeLists.txt
  2. 9
      Source/msg.cpp
  3. 46
      Source/quests/validation.cpp
  4. 17
      Source/quests/validation.hpp
  5. 3
      Source/textdat.cpp
  6. 2
      Source/textdat.h

2
Source/CMakeLists.txt

@ -152,6 +152,8 @@ set(libdevilutionx_SRCS
qol/stash.cpp
qol/xpbar.cpp
quests/validation.cpp
storm/storm_net.cpp
storm/storm_svid.cpp

9
Source/msg.cpp

@ -40,6 +40,7 @@
#include "pfile.h"
#include "plrmsg.h"
#include "portals/validation.hpp"
#include "quests/validation.hpp"
#include "spells.h"
#include "storm/storm_net.hpp"
#include "sync.h"
@ -296,6 +297,11 @@ bool IsPortalDeltaValid(const DPortal &portal)
return IsPortalDeltaValid(position, portal.level, portal.ltype, portal.setlvl);
}
bool IsQuestDeltaValid(quest_id qidx, const MultiQuests &quest)
{
return IsQuestDeltaValid(qidx, quest.qstate, quest.qlog, quest.qmsg);
}
uint8_t GetLevelForMultiplayer(uint8_t level, bool isSetLevel)
{
if (isSetLevel)
@ -711,6 +717,9 @@ const std::byte *DeltaImportJunk(const std::byte *src, const std::byte *end)
return nullptr;
}
memcpy(&sgJunk.quests[q], src, sizeof(MultiQuests));
if (!IsQuestDeltaValid(static_cast<quest_id>(qidx), sgJunk.quests[q])) {
sgJunk.quests[q].qstate = QUEST_INVALID;
}
src += sizeof(MultiQuests);
q++;
}

46
Source/quests/validation.cpp

@ -0,0 +1,46 @@
/**
* @file quests/validation.cpp
*
* Implementation of functions for validation of quest data.
*/
#include "quests/validation.hpp"
#include <cstdint>
#include "objdat.h"
#include "quests.h"
#include "textdat.h"
#include "utils/is_of.hpp"
namespace devilution {
bool IsQuestDeltaValid(quest_id qidx, quest_state qstate, uint8_t qlog, int16_t qmsg)
{
if (IsNoneOf(qlog, 0, 1))
return false;
if (qmsg < 0 || static_cast<size_t>(qmsg) >= SpeechCount)
return false;
switch (qstate) {
case QUEST_NOTAVAIL:
case QUEST_INIT:
case QUEST_ACTIVE:
case QUEST_DONE:
return true;
case QUEST_HIVE_TEASE1:
case QUEST_HIVE_TEASE2:
case QUEST_HIVE_ACTIVE:
return qidx == Q_JERSEY;
case QUEST_HIVE_DONE:
return IsAnyOf(qidx, Q_FARMER, Q_JERSEY);
default:
return false;
}
}
} // namespace devilution

17
Source/quests/validation.hpp

@ -0,0 +1,17 @@
/**
* @file quests/validation.hpp
*
* Interface of functions for validation of quest data.
*/
#pragma once
#include <cstdint>
#include "objdat.h"
#include "quests.h"
namespace devilution {
bool IsQuestDeltaValid(quest_id qidx, quest_state qstate, uint8_t qlog, int16_t qmsg);
} // namespace devilution

3
Source/textdat.cpp

@ -916,4 +916,7 @@ const Speech Speeches[] = {
1, 5, SfxID::Adria48 },
*/
};
const size_t SpeechCount = sizeof(Speeches) / sizeof(Speech);
} // namespace devilution

2
Source/textdat.h

@ -5,6 +5,7 @@
*/
#pragma once
#include <cstddef>
#include <cstdint>
#include "sound_effect_enums.h"
@ -430,6 +431,7 @@ struct Speech {
SfxID sfxnr;
};
extern const size_t SpeechCount;
extern const Speech Speeches[];
} // namespace devilution

Loading…
Cancel
Save