mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
Mod version verification system
This commit is contained in:
@ -532,6 +532,47 @@ JsonNode addMeta(JsonNode config, std::string meta)
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CModInfo::Version CModInfo::Version::GameVersion()
|
||||||
|
{
|
||||||
|
return Version(GameConstants::VCMI_VERSION_MAJOR, GameConstants::VCMI_VERSION_MINOR, GameConstants::VCMI_VERSION_PATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
CModInfo::Version CModInfo::Version::fromString(std::string from)
|
||||||
|
{
|
||||||
|
int major = 0, minor = 0, patch = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto pointPos = from.find('.');
|
||||||
|
major = std::stoi(from.substr(0, pointPos));
|
||||||
|
from = from.substr(pointPos);
|
||||||
|
pointPos = from.find('.');
|
||||||
|
minor = std::stoi(from.substr(0, pointPos));
|
||||||
|
patch = std::stoi(from.substr(pointPos));
|
||||||
|
}
|
||||||
|
catch(const std::invalid_argument & e)
|
||||||
|
{
|
||||||
|
return Version();
|
||||||
|
}
|
||||||
|
return Version(major, minor, patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CModInfo::Version::toString() const
|
||||||
|
{
|
||||||
|
return std::to_string(major) + '.' + std::to_string(minor) + '.' + std::to_string(patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CModInfo::Version::compatible(const Version & other, bool checkMinor, bool checkPatch) const
|
||||||
|
{
|
||||||
|
return (major == other.major &&
|
||||||
|
(!checkMinor || minor >= other.minor) &&
|
||||||
|
(!checkPatch || minor > other.minor || (minor == other.minor && patch >= other.patch)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CModInfo::Version::isNull() const
|
||||||
|
{
|
||||||
|
return major == 0 && minor == 0 && patch == 0;
|
||||||
|
}
|
||||||
|
|
||||||
CModInfo::CModInfo():
|
CModInfo::CModInfo():
|
||||||
checksum(0),
|
checksum(0),
|
||||||
enabled(false),
|
enabled(false),
|
||||||
@ -551,6 +592,12 @@ CModInfo::CModInfo(std::string identifier,const JsonNode & local, const JsonNode
|
|||||||
validation(PENDING),
|
validation(PENDING),
|
||||||
config(addMeta(config, identifier))
|
config(addMeta(config, identifier))
|
||||||
{
|
{
|
||||||
|
version = Version::fromString(config["version"].String());
|
||||||
|
if(!config["compatibility"].isNull())
|
||||||
|
{
|
||||||
|
vcmiCompatibleMin = Version::fromString(config["compatibility"]["min"].String());
|
||||||
|
vcmiCompatibleMax = Version::fromString(config["compatibility"]["max"].String());
|
||||||
|
}
|
||||||
loadLocalData(local);
|
loadLocalData(local);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,6 +649,10 @@ void CModInfo::loadLocalData(const JsonNode & data)
|
|||||||
checksum = strtol(data["checksum"].String().c_str(), nullptr, 16);
|
checksum = strtol(data["checksum"].String().c_str(), nullptr, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check compatibility
|
||||||
|
enabled &= vcmiCompatibleMin.isNull() || Version::GameVersion().compatible(vcmiCompatibleMin);
|
||||||
|
enabled &= vcmiCompatibleMax.isNull() || vcmiCompatibleMax.compatible(Version::GameVersion());
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
validation = validated ? PASSED : PENDING;
|
validation = validated ? PASSED : PENDING;
|
||||||
else
|
else
|
||||||
|
@ -178,6 +178,30 @@ public:
|
|||||||
PASSED
|
PASSED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Version
|
||||||
|
{
|
||||||
|
int major = 0;
|
||||||
|
int minor = 0;
|
||||||
|
int patch = 0;
|
||||||
|
|
||||||
|
Version() = default;
|
||||||
|
Version(int mj, int mi, int p): major(mj), minor(mi), patch(p) {}
|
||||||
|
|
||||||
|
static Version GameVersion();
|
||||||
|
static Version fromString(std::string from);
|
||||||
|
std::string toString() const;
|
||||||
|
|
||||||
|
bool compatible(const Version & other, bool checkMinor = false, bool checkPatch = false) const;
|
||||||
|
bool isNull() const;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & major;
|
||||||
|
h & minor;
|
||||||
|
h & patch;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// identifier, identical to name of folder with mod
|
/// identifier, identical to name of folder with mod
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
|
|
||||||
@ -185,6 +209,12 @@ public:
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
|
||||||
|
/// version of the mod
|
||||||
|
Version version;
|
||||||
|
|
||||||
|
///The vcmi versions compatible with the mod
|
||||||
|
Version vcmiCompatibleMin, vcmiCompatibleMax;
|
||||||
|
|
||||||
/// list of mods that should be loaded before this one
|
/// list of mods that should be loaded before this one
|
||||||
std::set <TModID> dependencies;
|
std::set <TModID> dependencies;
|
||||||
|
|
||||||
@ -210,7 +240,8 @@ public:
|
|||||||
static std::string getModDir(std::string name);
|
static std::string getModDir(std::string name);
|
||||||
static std::string getModFile(std::string name);
|
static std::string getModFile(std::string name);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
//TODO: remove as soon as backward compatilibity for versions earlier 806 is not preserved.
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int ver)
|
||||||
{
|
{
|
||||||
h & identifier;
|
h & identifier;
|
||||||
h & description;
|
h & description;
|
||||||
@ -257,6 +288,13 @@ class DLL_LINKAGE CModHandler
|
|||||||
void loadOneMod(std::string modName, std::string parent, const JsonNode & modSettings, bool enableMods);
|
void loadOneMod(std::string modName, std::string parent, const JsonNode & modSettings, bool enableMods);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
class Incompatibility: public std::logic_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Incompatibility(const std::string & w): std::logic_error(w)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
CIdentifierStorage identifiers;
|
CIdentifierStorage identifiers;
|
||||||
|
|
||||||
std::shared_ptr<CContentHandler> content; //(!)Do not serialize
|
std::shared_ptr<CContentHandler> content; //(!)Do not serialize
|
||||||
@ -336,8 +374,43 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & allMods;
|
if(version < 806)
|
||||||
|
{
|
||||||
|
h & allMods; //don't serialize mods
|
||||||
h & activeMods;
|
h & activeMods;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(h.saving)
|
||||||
|
{
|
||||||
|
h & activeMods;
|
||||||
|
for(auto & m : activeMods)
|
||||||
|
h & allMods[m].version;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<TModID> newActiveMods;
|
||||||
|
h & newActiveMods;
|
||||||
|
for(auto & m : newActiveMods)
|
||||||
|
{
|
||||||
|
if(!allMods.count(m))
|
||||||
|
throw Incompatibility(m + " unkown mod");
|
||||||
|
|
||||||
|
CModInfo::Version mver;
|
||||||
|
h & mver;
|
||||||
|
if(!allMods[m].version.isNull() && !mver.isNull() && !allMods[m].version.compatible(mver))
|
||||||
|
{
|
||||||
|
std::string err = allMods[m].name +
|
||||||
|
": version needed " + mver.toString() +
|
||||||
|
"but you have installed " + allMods[m].version.toString();
|
||||||
|
throw Incompatibility(err);
|
||||||
|
}
|
||||||
|
allMods[m].enabled = true;
|
||||||
|
}
|
||||||
|
std::swap(activeMods, newActiveMods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
h & settings;
|
h & settings;
|
||||||
h & modules;
|
h & modules;
|
||||||
h & identifiers;
|
h & identifiers;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "../ConstTransitivePtr.h"
|
#include "../ConstTransitivePtr.h"
|
||||||
#include "../GameConstants.h"
|
#include "../GameConstants.h"
|
||||||
|
|
||||||
const ui32 SERIALIZATION_VERSION = 805;
|
const ui32 SERIALIZATION_VERSION = 806;
|
||||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 805;
|
const ui32 MINIMAL_SERIALIZATION_VERSION = 805;
|
||||||
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user