mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Verifying mods before starting map
This commit is contained in:
parent
67e1b48d47
commit
954a2abb71
@ -131,6 +131,15 @@ void CLobbyScreen::startScenario(bool allowOnlyAI)
|
||||
CSH->sendStartGame(allowOnlyAI);
|
||||
buttonStart->block(true);
|
||||
}
|
||||
catch(CModHandler::Incompatibility & e)
|
||||
{
|
||||
logGlobal->warn("Incompatibility exception during start scenario: %s", e.what());
|
||||
|
||||
auto errorMsg = VLC->generaltexth->translate("vcmi.server.errors.modsIncompatibility") + '\n';
|
||||
errorMsg += e.what();
|
||||
|
||||
CInfoWindow::showInfoDialog(errorMsg, CInfoWindow::TCompsInfo(), PlayerColor(1));
|
||||
}
|
||||
catch(std::exception & e)
|
||||
{
|
||||
logGlobal->error("Exception during startScenario: %s", e.what());
|
||||
|
@ -967,6 +967,11 @@ std::vector<std::string> CModHandler::getActiveMods()
|
||||
return activeMods;
|
||||
}
|
||||
|
||||
const CModInfo & CModHandler::getModInfo(const TModID & modId) const
|
||||
{
|
||||
return allMods.at(modId);
|
||||
}
|
||||
|
||||
static JsonNode genDefaultFS()
|
||||
{
|
||||
// default FS config for mods: directory "Content" that acts as H3 root directory
|
||||
|
@ -174,7 +174,7 @@ public:
|
||||
const ContentTypeHandler & operator[] (const std::string & name) const;
|
||||
};
|
||||
|
||||
typedef std::string TModID;
|
||||
using TModID = std::string;
|
||||
|
||||
class DLL_LINKAGE CModInfo
|
||||
{
|
||||
@ -347,6 +347,8 @@ public:
|
||||
/// returns list of all (active) mods
|
||||
std::vector<std::string> getAllMods();
|
||||
std::vector<std::string> getActiveMods();
|
||||
|
||||
const CModInfo & getModInfo(const TModID & modId) const;
|
||||
|
||||
/// load content from all available mods
|
||||
void load();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mapping/CMapInfo.h"
|
||||
#include "mapping/CCampaignHandler.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "mapping/CMapService.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -67,8 +68,16 @@ std::string StartInfo::getCampaignName() const
|
||||
|
||||
void LobbyInfo::verifyStateBeforeStart(bool ignoreNoHuman) const
|
||||
{
|
||||
if(!mi)
|
||||
if(!mi || !mi->mapHeader)
|
||||
throw std::domain_error("ExceptionMapMissing");
|
||||
|
||||
auto missingMods = CMapService::verifyMapHeaderMods(*mi->mapHeader);
|
||||
CModHandler::Incompatibility::ModList modList;
|
||||
for(const auto & m : missingMods)
|
||||
modList.push_back({m.first, m.second.toString()});
|
||||
|
||||
if(!modList.empty())
|
||||
throw CModHandler::Incompatibility(std::move(modList));
|
||||
|
||||
//there must be at least one human player before game can be started
|
||||
std::map<PlayerColor, PlayerSettings>::const_iterator i;
|
||||
|
@ -275,6 +275,10 @@ enum EMapFormat: ui8
|
||||
};
|
||||
}
|
||||
|
||||
// Inherit from container to enable forward declaration
|
||||
class ModCompatibilityInfo: public std::map<TModID, CModInfo::Version>
|
||||
{};
|
||||
|
||||
/// The map header holds information about loss/victory condition,map format, version, players, height, width,...
|
||||
class DLL_LINKAGE CMapHeader
|
||||
{
|
||||
@ -295,7 +299,7 @@ public:
|
||||
ui8 levels() const;
|
||||
|
||||
EMapFormat::EMapFormat version; /// The default value is EMapFormat::SOD.
|
||||
std::map<TModID, CModInfo::Version> mods; /// set of mods required to play a map
|
||||
ModCompatibilityInfo mods; /// set of mods required to play a map
|
||||
|
||||
si32 height; /// The default value is 72.
|
||||
si32 width; /// The default value is 72.
|
||||
|
@ -86,6 +86,24 @@ void CMapService::saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::
|
||||
}
|
||||
}
|
||||
|
||||
ModCompatibilityInfo CMapService::verifyMapHeaderMods(const CMapHeader & map)
|
||||
{
|
||||
ModCompatibilityInfo modCompatibilityInfo;
|
||||
const auto & activeMods = VLC->modh->getActiveMods();
|
||||
for(const auto & mapMod : map.mods)
|
||||
{
|
||||
if(vstd::contains(activeMods, mapMod.first))
|
||||
{
|
||||
const auto & modInfo = VLC->modh->getModInfo(mapMod.first);
|
||||
if(modInfo.version.compatible(mapMod.second))
|
||||
continue;
|
||||
}
|
||||
|
||||
modCompatibilityInfo[mapMod.first] = mapMod.second;
|
||||
}
|
||||
return modCompatibilityInfo;
|
||||
}
|
||||
|
||||
std::unique_ptr<CInputStream> CMapService::getStreamFromFS(const ResourceID & name)
|
||||
{
|
||||
return CResourceHandler::get()->load(name);
|
||||
|
@ -21,6 +21,8 @@ class CInputStream;
|
||||
class IMapLoader;
|
||||
class IMapPatcher;
|
||||
|
||||
class ModCompatibilityInfo;
|
||||
|
||||
/**
|
||||
* The map service provides loading and saving of VCMI/H3 map files.
|
||||
*/
|
||||
@ -74,7 +76,15 @@ public:
|
||||
*/
|
||||
std::unique_ptr<CMapHeader> loadMapHeader(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const;
|
||||
|
||||
/**
|
||||
* Tests if mods used in the map are currently loaded
|
||||
* @param map const reference to map header
|
||||
* @return data structure representing missing or incompatible mods (those which are needed from map but not loaded)
|
||||
*/
|
||||
static ModCompatibilityInfo verifyMapHeaderMods(const CMapHeader & map);
|
||||
|
||||
void saveMap(const std::unique_ptr<CMap> & map, boost::filesystem::path fullPath) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Gets a map input stream object specified by a map name.
|
||||
|
Loading…
Reference in New Issue
Block a user