mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-10 22:31:40 +02:00
Restore save compatibility with 1.6
This commit is contained in:
@@ -14,10 +14,7 @@
|
||||
|
||||
#include "bonuses/Bonus.h"
|
||||
#include "bonuses/CBonusSystemNode.h"
|
||||
#include "GameConstants.h"
|
||||
#include "GameCallbackHolder.h"
|
||||
#include "IHandlerBase.h"
|
||||
#include "serializer/Serializeable.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@@ -180,82 +177,4 @@ private:
|
||||
void loadComponents(CArtifact * art, const JsonNode & node);
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE ArtSlotInfo : public GameCallbackHolder
|
||||
{
|
||||
ArtifactInstanceID artifactID;
|
||||
bool locked = false; //if locked, then artifact points to the combined artifact
|
||||
|
||||
explicit ArtSlotInfo(IGameCallback * cb);
|
||||
ArtSlotInfo(const CArtifactInstance * artifact, bool locked);
|
||||
|
||||
const CArtifactInstance * getArt() const;
|
||||
ArtifactInstanceID getID() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & artifactID;
|
||||
h & locked;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CArtifactSet : public virtual Serializeable
|
||||
{
|
||||
|
||||
public:
|
||||
using ArtPlacementMap = std::map<const CArtifactInstance*, ArtifactPosition>;
|
||||
|
||||
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
|
||||
std::map<ArtifactPosition, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
|
||||
ArtSlotInfo artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange
|
||||
|
||||
const ArtSlotInfo * getSlot(const ArtifactPosition & pos) const;
|
||||
void lockSlot(const ArtifactPosition & pos);
|
||||
const CArtifactInstance * getArt(const ArtifactPosition & pos, bool excludeLocked = true) const;
|
||||
ArtifactInstanceID getArtID(const ArtifactPosition & pos, bool excludeLocked = true) const;
|
||||
/// Looks for first artifact with given ID
|
||||
ArtifactPosition getArtPos(const ArtifactID & aid, bool onlyWorn = true, bool allowLocked = true) const;
|
||||
ArtifactPosition getArtPos(const CArtifactInstance * art) const;
|
||||
const CArtifactInstance * getArtByInstanceId(const ArtifactInstanceID & artInstId) const;
|
||||
bool hasArt(const ArtifactID & aid, bool onlyWorn = false, bool searchCombinedParts = false) const;
|
||||
bool isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck = false) const;
|
||||
|
||||
virtual IGameCallback * getCallback() const = 0;
|
||||
virtual ArtBearer::ArtBearer bearerType() const = 0;
|
||||
virtual ArtPlacementMap putArtifact(const ArtifactPosition & slot, const CArtifactInstance * art);
|
||||
virtual void removeArtifact(const ArtifactPosition & slot);
|
||||
CArtifactSet(IGameCallback * cb);
|
||||
virtual ~CArtifactSet() = default;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & artifactsInBackpack;
|
||||
h & artifactsWorn;
|
||||
}
|
||||
|
||||
void artDeserializationFix(CGameState * gs, CBonusSystemNode *node);
|
||||
|
||||
void serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map);
|
||||
const CArtifactInstance * getCombinedArtWithPart(const ArtifactID & partId) const;
|
||||
|
||||
private:
|
||||
void serializeJsonHero(JsonSerializeFormat & handler, CMap * map);
|
||||
void serializeJsonCreature(JsonSerializeFormat & handler);
|
||||
void serializeJsonCommander(JsonSerializeFormat & handler);
|
||||
|
||||
void serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map);//normal slots
|
||||
};
|
||||
|
||||
// Used to try on artifacts before the claimed changes have been applied
|
||||
class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet, public GameCallbackHolder
|
||||
{
|
||||
IGameCallback * getCallback() const final { return cb; }
|
||||
public:
|
||||
CArtifactFittingSet(IGameCallback *cb, ArtBearer::ArtBearer Bearer);
|
||||
explicit CArtifactFittingSet(const CArtifactSet & artSet);
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
|
||||
protected:
|
||||
ArtBearer::ArtBearer bearer;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "CArtifactInstance.h"
|
||||
|
||||
#include "CArtifactSet.h"
|
||||
#include "ArtifactUtils.h"
|
||||
#include "CArtHandler.h"
|
||||
#include "IGameCallback.h"
|
||||
@@ -189,4 +190,11 @@ void CArtifactInstance::attachToBonusSystem(CGameState * gs)
|
||||
attachToSource(*gs->getArtInstance(part.artifactID));
|
||||
}
|
||||
|
||||
void CArtifactInstance::saveCompatibilityFixArtifactID(std::shared_ptr<CArtifactInstance> self)
|
||||
{
|
||||
self->cb->gameState()->saveCompatibilityLastAllocatedArtifactID = ArtifactInstanceID(self->cb->gameState()->saveCompatibilityLastAllocatedArtifactID.getNum()+1);
|
||||
self->id = self->cb->gameState()->saveCompatibilityLastAllocatedArtifactID;
|
||||
self->cb->gameState()->saveCompatibilityUnregisteredArtifacts.push_back(self);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -10,41 +10,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "bonuses/CBonusSystemNode.h"
|
||||
#include "CArtHandler.h"
|
||||
#include "GameCallbackHolder.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct ArtifactLocation;
|
||||
class CGameState;
|
||||
class CArtifactSet;
|
||||
|
||||
class DLL_LINKAGE CCombinedArtifactInstance : public GameCallbackHolder
|
||||
{
|
||||
protected:
|
||||
using GameCallbackHolder::GameCallbackHolder;
|
||||
public:
|
||||
using ArtPlacementMap = std::map<const CArtifactInstance*, ArtifactPosition>;
|
||||
|
||||
struct PartInfo : public GameCallbackHolder
|
||||
{
|
||||
explicit PartInfo(IGameCallback * cb);
|
||||
PartInfo(const CArtifactInstance * artifact, ArtifactPosition slot);
|
||||
|
||||
|
||||
ArtifactInstanceID artifactID;
|
||||
ArtifactPosition slot;
|
||||
|
||||
const CArtifactInstance * getArtifact() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & artifactID;
|
||||
h & slot;
|
||||
}
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h);
|
||||
};
|
||||
void addPart(const CArtifactInstance * art, const ArtifactPosition & slot);
|
||||
// Checks if supposed part inst is part of this combined art inst
|
||||
bool isPart(const CArtifactInstance * supposedPart) const;
|
||||
bool hasParts() const;
|
||||
const std::vector<PartInfo> & getPartsInfo() const;
|
||||
void addPlacementMap(const CArtifactSet::ArtPlacementMap & placementMap);
|
||||
void addPlacementMap(const ArtPlacementMap & placementMap);
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
@@ -86,6 +85,8 @@ public:
|
||||
ArtifactInstanceID getId() const;
|
||||
void setId(ArtifactInstanceID id);
|
||||
|
||||
static void saveCompatibilityFixArtifactID(std::shared_ptr<CArtifactInstance> self);
|
||||
|
||||
bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE,
|
||||
bool assumeDestRemoved = false) const;
|
||||
bool isCombined() const;
|
||||
@@ -106,4 +107,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Handler>
|
||||
void CCombinedArtifactInstance::PartInfo::serialize(Handler & h)
|
||||
{
|
||||
if (h.saving || h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & artifactID;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CArtifactInstance> pointer;
|
||||
h & pointer;
|
||||
if (pointer->getId() == ArtifactInstanceID())
|
||||
CArtifactInstance::saveCompatibilityFixArtifactID(pointer);
|
||||
artifactID = pointer->getId();
|
||||
}
|
||||
h & slot;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
109
lib/CArtifactSet.h
Normal file
109
lib/CArtifactSet.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* CArtHandler.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CArtHandler.h"
|
||||
#include "GameCallbackHolder.h"
|
||||
#include "constants/EntityIdentifiers.h"
|
||||
|
||||
#include "CArtifactInstance.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct DLL_LINKAGE ArtSlotInfo : public GameCallbackHolder
|
||||
{
|
||||
ArtifactInstanceID artifactID;
|
||||
bool locked = false; //if locked, then artifact points to the combined artifact
|
||||
|
||||
explicit ArtSlotInfo(IGameCallback * cb);
|
||||
ArtSlotInfo(const CArtifactInstance * artifact, bool locked);
|
||||
|
||||
const CArtifactInstance * getArt() const;
|
||||
ArtifactInstanceID getID() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
if (h.saving || h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & artifactID;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CArtifactInstance> pointer;
|
||||
h & pointer;
|
||||
if (pointer->getId() == ArtifactInstanceID())
|
||||
CArtifactInstance::saveCompatibilityFixArtifactID(pointer);
|
||||
artifactID = pointer->getId();
|
||||
}
|
||||
h & locked;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CArtifactSet : public virtual Serializeable
|
||||
{
|
||||
|
||||
public:
|
||||
using ArtPlacementMap = std::map<const CArtifactInstance*, ArtifactPosition>;
|
||||
|
||||
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
|
||||
std::map<ArtifactPosition, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
|
||||
ArtSlotInfo artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange
|
||||
|
||||
const ArtSlotInfo * getSlot(const ArtifactPosition & pos) const;
|
||||
void lockSlot(const ArtifactPosition & pos);
|
||||
const CArtifactInstance * getArt(const ArtifactPosition & pos, bool excludeLocked = true) const;
|
||||
ArtifactInstanceID getArtID(const ArtifactPosition & pos, bool excludeLocked = true) const;
|
||||
/// Looks for first artifact with given ID
|
||||
ArtifactPosition getArtPos(const ArtifactID & aid, bool onlyWorn = true, bool allowLocked = true) const;
|
||||
ArtifactPosition getArtPos(const CArtifactInstance * art) const;
|
||||
const CArtifactInstance * getArtByInstanceId(const ArtifactInstanceID & artInstId) const;
|
||||
bool hasArt(const ArtifactID & aid, bool onlyWorn = false, bool searchCombinedParts = false) const;
|
||||
bool isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck = false) const;
|
||||
|
||||
virtual IGameCallback * getCallback() const = 0;
|
||||
virtual ArtBearer::ArtBearer bearerType() const = 0;
|
||||
virtual ArtPlacementMap putArtifact(const ArtifactPosition & slot, const CArtifactInstance * art);
|
||||
virtual void removeArtifact(const ArtifactPosition & slot);
|
||||
CArtifactSet(IGameCallback * cb);
|
||||
virtual ~CArtifactSet() = default;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & artifactsInBackpack;
|
||||
h & artifactsWorn;
|
||||
}
|
||||
|
||||
void artDeserializationFix(CGameState * gs, CBonusSystemNode *node);
|
||||
|
||||
void serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map);
|
||||
const CArtifactInstance * getCombinedArtWithPart(const ArtifactID & partId) const;
|
||||
|
||||
private:
|
||||
void serializeJsonHero(JsonSerializeFormat & handler, CMap * map);
|
||||
void serializeJsonCreature(JsonSerializeFormat & handler);
|
||||
void serializeJsonCommander(JsonSerializeFormat & handler);
|
||||
|
||||
void serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map);//normal slots
|
||||
};
|
||||
|
||||
// Used to try on artifacts before the claimed changes have been applied
|
||||
class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet, public GameCallbackHolder
|
||||
{
|
||||
IGameCallback * getCallback() const final { return cb; }
|
||||
public:
|
||||
CArtifactFittingSet(IGameCallback *cb, ArtBearer::ArtBearer Bearer);
|
||||
explicit CArtifactFittingSet(const CArtifactSet & artSet);
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
|
||||
protected:
|
||||
ArtBearer::ArtBearer bearer;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CArtHandler.h"
|
||||
#include "CArtifactSet.h"
|
||||
#include "CArtifactInstance.h"
|
||||
#include "CCreatureHandler.h"
|
||||
#include "GameCallbackHolder.h"
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "bonuses/BonusCache.h"
|
||||
#include "bonuses/CBonusSystemNode.h"
|
||||
#include "serializer/Serializeable.h"
|
||||
#include "mapObjects/CGObjectInstance.h"
|
||||
|
||||
#include <vcmi/Entity.h>
|
||||
|
||||
@@ -98,7 +99,17 @@ public:
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
||||
h & static_cast<CArtifactSet&>(*this);
|
||||
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & armyInstanceID;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CGObjectInstance> army;
|
||||
h & army;
|
||||
armyInstanceID = army->id;
|
||||
}
|
||||
h & experience;
|
||||
}
|
||||
|
||||
|
@@ -692,6 +692,7 @@ set(lib_MAIN_HEADERS
|
||||
CAndroidVMHelper.h
|
||||
CArtHandler.h
|
||||
CArtifactInstance.h
|
||||
CArtifactSet.h
|
||||
CBonusTypeHandler.h
|
||||
CCreatureHandler.h
|
||||
CCreatureSet.h
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "TurnTimerInfo.h"
|
||||
#include "bonuses/Bonus.h"
|
||||
#include "bonuses/CBonusSystemNode.h"
|
||||
#include "mapObjects/CGObjectInstance.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@@ -117,7 +118,16 @@ public:
|
||||
h & status;
|
||||
h & turnTimer;
|
||||
h & *playerLocalSettings;
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
h & ownedObjects;
|
||||
else
|
||||
{
|
||||
std::vector<std::shared_ptr<CGObjectInstance>> objectPtrs;
|
||||
h & objectPtrs;
|
||||
for (const auto & ptr : objectPtrs)
|
||||
ownedObjects.push_back(ptr->id);
|
||||
}
|
||||
|
||||
h & quests;
|
||||
h & visitedObjects;
|
||||
h & visitedObjectsGlobal;
|
||||
|
@@ -1571,6 +1571,8 @@ void CGameState::buildBonusSystemTree()
|
||||
|
||||
void CGameState::restoreBonusSystemTree()
|
||||
{
|
||||
heroesPool->setGameState(this);
|
||||
|
||||
buildGlobalTeamPlayerTree();
|
||||
for(auto & armed : map->getObjects<CArmedInstance>())
|
||||
armed->restoreBonusSystem(this);
|
||||
@@ -1759,13 +1761,35 @@ void CGameState::loadGame(CLoadFile & file)
|
||||
logGlobal->info("Loading game state...");
|
||||
|
||||
CMapHeader dummyHeader;
|
||||
StartInfo dummyStartInfo;
|
||||
auto startInfo = std::make_shared<StartInfo>();
|
||||
ActiveModsInSaveList dummyActiveMods;
|
||||
|
||||
file.load(dummyHeader);
|
||||
file.load(dummyStartInfo);
|
||||
if (file.hasFeature(ESerializationVersion::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
file.load(startInfo);
|
||||
file.load(dummyActiveMods);
|
||||
file.load(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool dummyA = false;
|
||||
uint32_t dummyB = 0;
|
||||
uint16_t dummyC = 0;
|
||||
file.load(startInfo);
|
||||
file.load(dummyActiveMods);
|
||||
file.load(dummyA);
|
||||
file.load(dummyB);
|
||||
file.load(dummyC);
|
||||
file.load(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameState::saveCompatibilityRegisterMissingArtifacts()
|
||||
{
|
||||
for( const auto & newArtifact : saveCompatibilityUnregisteredArtifacts)
|
||||
map->saveCompatibilityAddMissingArtifact(newArtifact);
|
||||
saveCompatibilityUnregisteredArtifacts.clear();
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -49,10 +49,15 @@ class DLL_LINKAGE CGameState : public CNonConstInfoCallback, public Serializeabl
|
||||
{
|
||||
friend class CGameStateCampaign;
|
||||
|
||||
std::unique_ptr<StartInfo> initialOpts; //copy of settings received from pregame (not randomized)
|
||||
std::unique_ptr<StartInfo> scenarioOps;
|
||||
std::shared_ptr<StartInfo> initialOpts; //copy of settings received from pregame (not randomized)
|
||||
std::shared_ptr<StartInfo> scenarioOps;
|
||||
std::unique_ptr<CMap> map;
|
||||
|
||||
void saveCompatibilityRegisterMissingArtifacts();
|
||||
public:
|
||||
ArtifactInstanceID saveCompatibilityLastAllocatedArtifactID;
|
||||
std::vector<std::shared_ptr<CArtifactInstance>> saveCompatibilityUnregisteredArtifacts;
|
||||
|
||||
/// Stores number of times each artifact was placed on map via randomization
|
||||
std::map<ArtifactID, int> allocatedArtifacts;
|
||||
|
||||
@@ -180,9 +185,14 @@ public:
|
||||
h & actingPlayers;
|
||||
h & day;
|
||||
h & map;
|
||||
if (!h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
saveCompatibilityRegisterMissingArtifacts();
|
||||
h & players;
|
||||
h & teams;
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
h & *heroesPool;
|
||||
else
|
||||
h & heroesPool;
|
||||
h & globalEffects;
|
||||
h & currentRumor;
|
||||
h & campaign;
|
||||
|
@@ -21,6 +21,11 @@ TavernHeroesPool::TavernHeroesPool(CGameState * owner)
|
||||
: owner(owner)
|
||||
{}
|
||||
|
||||
void TavernHeroesPool::setGameState(CGameState * newOwner)
|
||||
{
|
||||
owner = newOwner;
|
||||
}
|
||||
|
||||
std::map<HeroTypeID, CGHeroInstance*> TavernHeroesPool::unusedHeroesFromPool() const
|
||||
{
|
||||
std::map<HeroTypeID, CGHeroInstance*> pool;
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "../GameConstants.h"
|
||||
#include "TavernSlot.h"
|
||||
#include "../mapObjects/CGObjectInstance.h"
|
||||
#include "../serializer/Serializeable.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@@ -33,8 +34,18 @@ class DLL_LINKAGE TavernHeroesPool : public Serializeable
|
||||
PlayerColor player;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & hero;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CGObjectInstance> pointer;
|
||||
h & pointer;
|
||||
hero = HeroTypeID(pointer->subID);
|
||||
}
|
||||
|
||||
h & slot;
|
||||
h & role;
|
||||
h & player;
|
||||
@@ -52,8 +63,11 @@ class DLL_LINKAGE TavernHeroesPool : public Serializeable
|
||||
std::vector<TavernSlot> currentTavern;
|
||||
|
||||
public:
|
||||
TavernHeroesPool() = default;
|
||||
TavernHeroesPool(CGameState * owner);
|
||||
|
||||
void setGameState(CGameState * owner);
|
||||
|
||||
/// Returns heroes currently available in tavern of a specific player
|
||||
std::vector<const CGHeroInstance *> getHeroesFor(PlayerColor color) const;
|
||||
|
||||
@@ -80,7 +94,15 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
h & heroesPool;
|
||||
else
|
||||
{
|
||||
std::map<HeroTypeID, std::shared_ptr<CGObjectInstance>> objectPtrs;
|
||||
h & objectPtrs;
|
||||
for (const auto & ptr : objectPtrs)
|
||||
heroesPool.push_back(ptr.first);
|
||||
}
|
||||
h & perPlayerAvailability;
|
||||
h & currentTavern;
|
||||
}
|
||||
|
@@ -378,8 +378,23 @@ public:
|
||||
h & patrol;
|
||||
h & moveDir;
|
||||
h & skillsInfo;
|
||||
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & visitedTown;
|
||||
h & boardedBoat;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CGObjectInstance> ptrTown;
|
||||
std::shared_ptr<CGObjectInstance> ptrBoat;
|
||||
h & ptrTown;
|
||||
h & ptrBoat;
|
||||
|
||||
visitedTown = ptrTown ? ptrTown->id : ObjectInstanceID();
|
||||
boardedBoat = ptrBoat ? ptrBoat->id : ObjectInstanceID();
|
||||
}
|
||||
|
||||
h & commander;
|
||||
h & visitedObjects;
|
||||
}
|
||||
|
@@ -84,8 +84,23 @@ public:
|
||||
h & built;
|
||||
h & destroyed;
|
||||
h & identifier;
|
||||
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & garrisonHero;
|
||||
h & visitingHero;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CGObjectInstance> ptrGarr;
|
||||
std::shared_ptr<CGObjectInstance> ptrVisit;
|
||||
h & ptrGarr;
|
||||
h & ptrVisit;
|
||||
|
||||
garrisonHero = ptrGarr ? ptrGarr->id : ObjectInstanceID();
|
||||
visitingHero = ptrVisit ? ptrVisit->id : ObjectInstanceID();
|
||||
}
|
||||
|
||||
h & alignmentToPlayer;
|
||||
h & forbiddenBuildings;
|
||||
h & builtBuildings;
|
||||
|
@@ -416,7 +416,7 @@ void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fi
|
||||
}
|
||||
|
||||
IQuestObject::IQuestObject()
|
||||
:quest(std::make_unique<CQuest>())
|
||||
:quest(std::make_shared<CQuest>())
|
||||
{}
|
||||
|
||||
IQuestObject::~IQuestObject() = default;
|
||||
|
@@ -118,7 +118,7 @@ public:
|
||||
|
||||
class DLL_LINKAGE IQuestObject
|
||||
{
|
||||
std::unique_ptr<CQuest> quest;
|
||||
std::shared_ptr<CQuest> quest; // TODO: not actually shared, replace with unique_ptr once 1.6 save compat is not needed
|
||||
public:
|
||||
IQuestObject();
|
||||
virtual ~IQuestObject();
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "../networkPacks/TradeItem.h"
|
||||
#include "../constants/Enumerations.h"
|
||||
#include "../CArtHandler.h"
|
||||
#include "../CArtifactSet.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
|
@@ -119,8 +119,19 @@ public:
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & message;
|
||||
if (h.saving || h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & storedArtifact;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CArtifactInstance> pointer;
|
||||
h & pointer;
|
||||
if (pointer->getId() == ArtifactInstanceID())
|
||||
CArtifactInstance::saveCompatibilityFixArtifactID(pointer);
|
||||
storedArtifact = pointer->getId();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||
};
|
||||
@@ -312,7 +323,17 @@ public:
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & direction;
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & boardedHeroID;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<CGObjectInstance> ptr;
|
||||
h & ptr;
|
||||
boardedHeroID = ptr ? ptr->id : ObjectInstanceID();
|
||||
}
|
||||
|
||||
h & layer;
|
||||
h & onboardAssaultAllowed;
|
||||
h & onboardVisitAllowed;
|
||||
|
@@ -10,24 +10,28 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMap.h"
|
||||
|
||||
#include "CMapEditManager.h"
|
||||
#include "CMapOperation.h"
|
||||
|
||||
#include "../CArtHandler.h"
|
||||
#include "../GameLibrary.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CSkillHandler.h"
|
||||
#include "../GameLibrary.h"
|
||||
#include "../GameSettings.h"
|
||||
#include "../IGameCallback.h"
|
||||
#include "../RiverHandler.h"
|
||||
#include "../RoadHandler.h"
|
||||
#include "../TerrainHandler.h"
|
||||
|
||||
#include "../entities/hero/CHeroHandler.h"
|
||||
#include "../gameState/CGameState.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../mapObjects/CGTownInstance.h"
|
||||
#include "../mapObjects/CQuest.h"
|
||||
#include "../mapObjects/ObjectTemplate.h"
|
||||
#include "../texts/CGeneralTextHandler.h"
|
||||
#include "../spells/CSpellHandler.h"
|
||||
#include "../CSkillHandler.h"
|
||||
#include "CMapEditManager.h"
|
||||
#include "CMapOperation.h"
|
||||
#include "../serializer/JsonSerializeFormat.h"
|
||||
#include "../spells/CSpellHandler.h"
|
||||
#include "../texts/CGeneralTextHandler.h"
|
||||
|
||||
#include <vstd/RNG.h>
|
||||
|
||||
@@ -930,4 +934,16 @@ const CGObjectInstance * CMap::getObject(ObjectInstanceID obj) const
|
||||
return objects.at(obj).get();
|
||||
}
|
||||
|
||||
void CMap::saveCompatibilityStoreAllocatedArtifactID()
|
||||
{
|
||||
if (!artInstances.empty())
|
||||
cb->gameState()->saveCompatibilityLastAllocatedArtifactID = artInstances.back()->getId();
|
||||
}
|
||||
|
||||
void CMap::saveCompatibilityAddMissingArtifact(std::shared_ptr<CArtifactInstance> artifact)
|
||||
{
|
||||
assert(artifact->getId().getNum() == artInstances.size());
|
||||
artInstances.push_back(artifact);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "CMapDefines.h"
|
||||
#include "CMapHeader.h"
|
||||
|
||||
#include "../mapObjects/CGObjectInstance.h"
|
||||
#include "../GameCallbackHolder.h"
|
||||
#include "../networkPacks/TradeItem.h"
|
||||
|
||||
@@ -95,6 +96,7 @@ public:
|
||||
|
||||
void calculateGuardingGreaturePositions();
|
||||
|
||||
void saveCompatibilityAddMissingArtifact(std::shared_ptr<CArtifactInstance> artifact);
|
||||
CArtifactInstance * createScroll(const SpellID & spellId);
|
||||
CArtifactInstance * createArtifact(const ArtifactID & artId, const SpellID & spellId = SpellID::NONE);
|
||||
CArtifactInstance * createSingleArtifact(const ArtifactID & artId, const SpellID & spellId = SpellID::NONE);
|
||||
@@ -240,6 +242,7 @@ public:
|
||||
const IGameSettings & getSettings() const;
|
||||
|
||||
void postInitialize();
|
||||
void saveCompatibilityStoreAllocatedArtifactID();
|
||||
|
||||
private:
|
||||
/// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground
|
||||
@@ -261,15 +264,43 @@ public:
|
||||
h & grailPos;
|
||||
h & artInstances;
|
||||
|
||||
if (!h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
saveCompatibilityStoreAllocatedArtifactID();
|
||||
std::vector< std::shared_ptr<CQuest> > quests;
|
||||
h & quests;
|
||||
}
|
||||
h & heroesPool;
|
||||
|
||||
//TODO: viccondetails
|
||||
h & terrain;
|
||||
h & guardingCreaturePositions;
|
||||
|
||||
h & objects;
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
h & heroesOnMap;
|
||||
h & heroesPool;
|
||||
else
|
||||
{
|
||||
std::vector<std::shared_ptr<CGObjectInstance>> objectPtrs;
|
||||
h & objectPtrs;
|
||||
for (const auto & ptr : objectPtrs)
|
||||
heroesOnMap.push_back(ptr->id);
|
||||
|
||||
for (auto & ptr : heroesPool)
|
||||
if (vstd::contains(objects, ptr))
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
h & teleportChannels;
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
h & towns;
|
||||
else
|
||||
{
|
||||
std::vector<std::shared_ptr<CGObjectInstance>> objectPtrs;
|
||||
h & objectPtrs;
|
||||
for (const auto & ptr : objectPtrs)
|
||||
towns.push_back(ptr->id);
|
||||
}
|
||||
h & artInstances;
|
||||
|
||||
// static members
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "../texts/MetaString.h"
|
||||
#include "../GameLibrary.h"
|
||||
#include "../TerrainHandler.h"
|
||||
#include "../mapObjects/CGObjectInstance.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@@ -139,9 +140,25 @@ struct DLL_LINKAGE TerrainTile
|
||||
h & roadType;
|
||||
h & roadDir;
|
||||
h & extTileFlags;
|
||||
|
||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
{
|
||||
h & visitableObjects;
|
||||
h & blockingObjects;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::shared_ptr<CGObjectInstance>> objectPtrs;
|
||||
h & objectPtrs;
|
||||
for (const auto & ptr : objectPtrs)
|
||||
visitableObjects.push_back(ptr->id);
|
||||
h & objectPtrs;
|
||||
for (const auto & ptr : objectPtrs)
|
||||
blockingObjects.push_back(ptr->id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
inline bool TerrainTile::hasFavorableWinds() const
|
||||
|
@@ -64,7 +64,11 @@ void CMapInfo::saveInit(const ResourcePath & file)
|
||||
mapHeader = std::make_unique<CMapHeader>();
|
||||
scenarioOptionsOfSave = std::make_unique<StartInfo>();
|
||||
lf.load(*mapHeader);
|
||||
if (lf.hasFeature(ESerializationVersion::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||
lf.load(*scenarioOptionsOfSave);
|
||||
else
|
||||
lf.load(scenarioOptionsOfSave);
|
||||
|
||||
fileURI = file.getName();
|
||||
originalFileURI = file.getOriginalName();
|
||||
fullFileURI = getFullFileURI(file);
|
||||
|
@@ -2459,15 +2459,13 @@ ArtSlotInfo::ArtSlotInfo(const CArtifactInstance * artifact, bool locked)
|
||||
|
||||
const CArtifactInstance * ArtSlotInfo::getArt() const
|
||||
{
|
||||
if(locked || !artifactID.hasValue())
|
||||
if(!artifactID.hasValue())
|
||||
return nullptr;
|
||||
return cb->getArtInstance(artifactID);
|
||||
}
|
||||
|
||||
ArtifactInstanceID ArtSlotInfo::getID() const
|
||||
{
|
||||
if(locked)
|
||||
return {};
|
||||
return artifactID;
|
||||
}
|
||||
|
||||
|
@@ -44,6 +44,12 @@ public:
|
||||
{
|
||||
loadedPointers.clear();
|
||||
loadedSharedPointers.clear();
|
||||
loadedUniquePointers.clear();
|
||||
}
|
||||
|
||||
bool hasFeature(Version v) const
|
||||
{
|
||||
return version >= v;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -51,6 +57,7 @@ private:
|
||||
|
||||
std::vector<std::string> loadedStrings;
|
||||
std::map<uint32_t, Serializeable *> loadedPointers;
|
||||
std::set<Serializeable *> loadedUniquePointers;
|
||||
std::map<const Serializeable *, std::shared_ptr<Serializeable>> loadedSharedPointers;
|
||||
IBinaryReader * reader;
|
||||
|
||||
@@ -156,6 +163,7 @@ private:
|
||||
{
|
||||
uint8_t read;
|
||||
load(read);
|
||||
assert(read == 0 || read == 1);
|
||||
data = static_cast<bool>(read);
|
||||
}
|
||||
|
||||
@@ -168,6 +176,7 @@ private:
|
||||
data.resize(length, T(cb));
|
||||
else
|
||||
data.resize(length);
|
||||
|
||||
for(uint32_t i=0;i<length;i++)
|
||||
load( data[i]);
|
||||
}
|
||||
@@ -212,6 +221,9 @@ private:
|
||||
// We already got this pointer
|
||||
// Cast it in case we are loading it to a non-first base pointer
|
||||
data = dynamic_cast<T>(i->second);
|
||||
if (vstd::contains(loadedUniquePointers, data))
|
||||
throw std::runtime_error("Attempt to deserialize duplicated unique_ptr!");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -236,7 +248,10 @@ private:
|
||||
data = nullptr;
|
||||
return;
|
||||
}
|
||||
auto dataNonConst = dynamic_cast<ncpT *>(app->createPtr(*this, cb));
|
||||
auto createdPtr = app->createPtr(*this, cb);
|
||||
auto dataNonConst = dynamic_cast<ncpT *>(createdPtr);
|
||||
assert(createdPtr);
|
||||
assert(dataNonConst);
|
||||
data = dataNonConst;
|
||||
ptrAllocated(data, pid);
|
||||
app->loadPtr(*this, cb, dataNonConst);
|
||||
@@ -300,6 +315,7 @@ private:
|
||||
T * internalPtr;
|
||||
loadRawPointer(internalPtr);
|
||||
data.reset(internalPtr);
|
||||
loadedUniquePointers.insert(internalPtr);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
@@ -321,7 +337,6 @@ private:
|
||||
data.insert(ins);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void load(std::unordered_set<T, U> &data)
|
||||
{
|
||||
|
@@ -47,6 +47,11 @@ public:
|
||||
savedPointers.clear();
|
||||
}
|
||||
|
||||
bool hasFeature(Version v) const
|
||||
{
|
||||
return version >= v;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, uint32_t> savedStrings;
|
||||
std::map<const Serializeable*, uint32_t> savedPointers;
|
||||
@@ -97,6 +102,7 @@ private:
|
||||
void save(const T & data)
|
||||
{
|
||||
uint8_t writ = static_cast<uint8_t>(data);
|
||||
assert(writ == 0 || writ == 1);
|
||||
save(writ);
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,13 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
template <typename From, typename To>
|
||||
struct static_caster
|
||||
{
|
||||
To operator()(From p) {return static_cast<To>(p);}
|
||||
};
|
||||
|
||||
|
||||
CLoadFile::CLoadFile(const boost::filesystem::path & fname, IGameCallback * cb)
|
||||
: serializer(this)
|
||||
, fName(fname.string())
|
||||
@@ -28,12 +35,13 @@ CLoadFile::CLoadFile(const boost::filesystem::path & fname, IGameCallback * cb)
|
||||
throw std::runtime_error("Error: cannot open file '" + fName + "' for reading!");
|
||||
|
||||
//we can read
|
||||
char buffer[4];
|
||||
sfile.read(buffer, 4);
|
||||
if(std::memcmp(buffer, "VCMI", 4) != 0)
|
||||
char magic[4];
|
||||
sfile.read(magic, 4);
|
||||
if(std::memcmp(magic, "VCMI", 4) != 0)
|
||||
throw std::runtime_error("Error: '" + fName + "' is not a VCMI file!");
|
||||
|
||||
serializer & serializer.version;
|
||||
sfile.read(reinterpret_cast<char*>(&serializer.version), sizeof(serializer.version));
|
||||
|
||||
if(serializer.version < ESerializationVersion::MINIMAL)
|
||||
throw std::runtime_error("Error: too old file format detected in '" + fName + "'!");
|
||||
|
||||
|
@@ -28,9 +28,14 @@ public:
|
||||
template<class T>
|
||||
void load(T & data)
|
||||
{
|
||||
static_assert(is_serializeable<BinaryDeserializer, T>::value, "This class can't be deserialized (possible pointer?)");
|
||||
//static_assert(is_serializeable<BinaryDeserializer, T>::value, "This class can't be deserialized (possible pointer?)");
|
||||
serializer & data;
|
||||
}
|
||||
|
||||
bool hasFeature(BinaryDeserializer::Version v) const
|
||||
{
|
||||
return serializer.version >= v;
|
||||
}
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@@ -32,12 +32,12 @@ enum class ESerializationVersion : int32_t
|
||||
NONE = 0,
|
||||
|
||||
RELEASE_160 = 873,
|
||||
MINIMAL = RELEASE_160,
|
||||
|
||||
MAP_HEADER_DISPOSED_HEROES, // map header contains disposed heroes list
|
||||
NO_RAW_POINTERS_IN_SERIALIZER, // large rework that removed all non-owning pointers from serializer
|
||||
|
||||
CURRENT = NO_RAW_POINTERS_IN_SERIALIZER,
|
||||
MINIMAL = CURRENT,
|
||||
};
|
||||
|
||||
static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");
|
||||
|
Reference in New Issue
Block a user