1
0
mirror of https://github.com/vcmi/vcmi.git synced 2026-05-22 09:55:17 +02:00

Merge pull request #3997 from IvanSavenko/serialization_refactor

[1.6] Serialization refactor
This commit is contained in:
Ivan Savenko
2024-05-30 19:13:21 +03:00
committed by GitHub
64 changed files with 414 additions and 673 deletions
-8
View File
@@ -14,14 +14,6 @@
#include "../../lib/CStack.h" #include "../../lib/CStack.h"
#include "../../lib/battle/BattleAction.h" #include "../../lib/battle/BattleAction.h"
void CEmptyAI::saveGame(BinarySerializer & h)
{
}
void CEmptyAI::loadGame(BinaryDeserializer & h)
{
}
void CEmptyAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) void CEmptyAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB)
{ {
cb = CB; cb = CB;
-3
View File
@@ -19,9 +19,6 @@ class CEmptyAI : public CGlobalAI
std::shared_ptr<CCallback> cb; std::shared_ptr<CCallback> cb;
public: public:
void saveGame(BinarySerializer & h) override;
void loadGame(BinaryDeserializer & h) override;
void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override; void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
void yourTurn(QueryID queryID) override; void yourTurn(QueryID queryID) override;
void yourTacticPhase(const BattleID & battleID, int distance) override; void yourTacticPhase(const BattleID & battleID, int distance) override;
-21
View File
@@ -772,27 +772,6 @@ void AIGateway::showMapObjectSelectDialog(QueryID askID, const Component & icon,
requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); }); requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); });
} }
void AIGateway::saveGame(BinarySerializer & h)
{
NET_EVENT_HANDLER;
nullkiller->memory->removeInvisibleObjects(myCb.get());
CAdventureAI::saveGame(h);
serializeInternal(h);
}
void AIGateway::loadGame(BinaryDeserializer & h)
{
//NET_EVENT_HANDLER;
#if 0
//disabled due to issue 2890
registerGoals(h);
#endif // 0
CAdventureAI::loadGame(h);
serializeInternal(h);
}
bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj) bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj)
{ {
if(!obj) if(!obj)
-22
View File
@@ -60,15 +60,6 @@ public:
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID); void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
void receivedAnswerConfirmation(int answerRequestID, int result); void receivedAnswerConfirmation(int answerRequestID, int result);
void heroVisit(const CGObjectInstance * obj, bool started); void heroVisit(const CGObjectInstance * obj, bool started);
template<typename Handler> void serialize(Handler & h)
{
h & battle;
h & remainingQueries;
h & requestToQueryID;
h & havingTurn;
}
}; };
// The gateway is responsible for AI events handling. Copied from VCAI.h and refined a bit // The gateway is responsible for AI events handling. Copied from VCAI.h and refined a bit
@@ -120,8 +111,6 @@ public:
void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override; void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override; void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
void saveGame(BinarySerializer & h) override; //saving
void loadGame(BinaryDeserializer & h) override; //loading
void finish() override; void finish() override;
void availableCreaturesChanged(const CGDwelling * town) override; void availableCreaturesChanged(const CGDwelling * town) override;
@@ -203,17 +192,6 @@ public:
void answerQuery(QueryID queryID, int selection); void answerQuery(QueryID queryID, int selection);
//special function that can be called ONLY from game events handling thread and will send request ASAP //special function that can be called ONLY from game events handling thread and will send request ASAP
void requestActionASAP(std::function<void()> whatToDo); void requestActionASAP(std::function<void()> whatToDo);
template<typename Handler> void serializeInternal(Handler & h)
{
h & nullkiller->memory->knownTeleportChannels;
h & nullkiller->memory->knownSubterraneanGates;
h & destinationTeleport;
h & nullkiller->memory->visitableObjs;
h & nullkiller->memory->alreadyVisited;
h & status;
h & battlename;
}
}; };
} }
-14
View File
@@ -111,14 +111,6 @@ public:
const CGHeroInstance * get(bool doWeExpectNull = false) const; const CGHeroInstance * get(bool doWeExpectNull = false) const;
const CGHeroInstance * get(const CPlayerSpecificInfoCallback * cb, bool doWeExpectNull = false) const; const CGHeroInstance * get(const CPlayerSpecificInfoCallback * cb, bool doWeExpectNull = false) const;
bool validAndSet() const; bool validAndSet() const;
template<typename Handler> void serialize(Handler & handler)
{
handler & h;
handler & hid;
handler & name;
}
}; };
enum BattleState enum BattleState
@@ -143,12 +135,6 @@ struct ObjectIdRef
ObjectIdRef(const CGObjectInstance * obj); ObjectIdRef(const CGObjectInstance * obj);
bool operator<(const ObjectIdRef & rhs) const; bool operator<(const ObjectIdRef & rhs) const;
template<typename Handler> void serialize(Handler & h)
{
h & id;
}
}; };
template<Obj::Type id> template<Obj::Type id>
-6
View File
@@ -36,12 +36,6 @@ namespace Goals
{ {
return new T(static_cast<T const &>(*this)); //casting enforces template instantiation return new T(static_cast<T const &>(*this)); //casting enforces template instantiation
} }
template<typename Handler> void serialize(Handler & h)
{
h & static_cast<AbstractGoal &>(*this);
//h & goalType & isElementar & isAbstract & priority;
//h & value & resID & objid & aid & tile & hero & town & bid;
}
bool operator==(const AbstractGoal & g) const override bool operator==(const AbstractGoal & g) const override
{ {
-14
View File
@@ -68,14 +68,6 @@ public:
const CGHeroInstance * get(bool doWeExpectNull = false) const; const CGHeroInstance * get(bool doWeExpectNull = false) const;
bool validAndSet() const; bool validAndSet() const;
template<typename Handler> void serialize(Handler & h)
{
h & this->h;
h & hid;
h & name;
}
}; };
enum BattleState enum BattleState
@@ -100,12 +92,6 @@ struct ObjectIdRef
ObjectIdRef(const CGObjectInstance * obj); ObjectIdRef(const CGObjectInstance * obj);
bool operator<(const ObjectIdRef & rhs) const; bool operator<(const ObjectIdRef & rhs) const;
template<typename Handler> void serialize(Handler & h)
{
h & id;
}
}; };
struct TimeCheck struct TimeCheck
-17
View File
@@ -73,7 +73,6 @@ namespace Goals
public: public:
bool operator==(const TSubgoal & rhs) const; bool operator==(const TSubgoal & rhs) const;
bool operator<(const TSubgoal & rhs) const; bool operator<(const TSubgoal & rhs) const;
//TODO: serialize?
}; };
using TGoalVec = std::vector<TSubgoal>; using TGoalVec = std::vector<TSubgoal>;
@@ -175,21 +174,5 @@ namespace Goals
// { // {
// return !(*this == g); // return !(*this == g);
// } // }
template<typename Handler> void serialize(Handler & h)
{
h & goalType;
h & isElementar;
h & isAbstract;
h & priority;
h & value;
h & resID;
h & objid;
h & aid;
h & tile;
h & hero;
h & town;
h & bid;
}
}; };
} }
-6
View File
@@ -69,12 +69,6 @@ namespace Goals
return ptr; return ptr;
} }
template<typename Handler> void serialize(Handler & h)
{
h & static_cast<AbstractGoal &>(*this);
//h & goalType & isElementar & isAbstract & priority;
//h & value & resID & objid & aid & tile & hero & town & bid;
}
bool operator==(const AbstractGoal & g) const override bool operator==(const AbstractGoal & g) const override
{ {
+5 -5
View File
@@ -53,7 +53,7 @@ namespace Goals
{ {
int3 tile = int3(0, 0, ourPos.z); int3 tile = int3(0, 0, ourPos.z);
const auto & slice = (*(ts->fogOfWarMap))[ourPos.z]; const auto & slice = ts->fogOfWarMap[ourPos.z];
for(tile.x = ourPos.x - scanRadius; tile.x <= ourPos.x + scanRadius; tile.x++) for(tile.x = ourPos.x - scanRadius; tile.x <= ourPos.x + scanRadius; tile.x++)
{ {
@@ -81,13 +81,13 @@ namespace Goals
foreach_tile_pos([&](const int3 & pos) foreach_tile_pos([&](const int3 & pos)
{ {
if((*(ts->fogOfWarMap))[pos.z][pos.x][pos.y]) if(ts->fogOfWarMap[pos.z][pos.x][pos.y])
{ {
bool hasInvisibleNeighbor = false; bool hasInvisibleNeighbor = false;
foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour) foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour)
{ {
if(!(*(ts->fogOfWarMap))[neighbour.z][neighbour.x][neighbour.y]) if(!ts->fogOfWarMap[neighbour.z][neighbour.x][neighbour.y])
{ {
hasInvisibleNeighbor = true; hasInvisibleNeighbor = true;
} }
@@ -171,7 +171,7 @@ namespace Goals
{ {
foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour) foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
{ {
if((*(ts->fogOfWarMap))[neighbour.z][neighbour.x][neighbour.y]) if(ts->fogOfWarMap[neighbour.z][neighbour.x][neighbour.y])
{ {
out.push_back(neighbour); out.push_back(neighbour);
} }
@@ -184,7 +184,7 @@ namespace Goals
int ret = 0; int ret = 0;
int3 npos = int3(0, 0, pos.z); int3 npos = int3(0, 0, pos.z);
const auto & slice = (*(ts->fogOfWarMap))[pos.z]; const auto & slice = ts->fogOfWarMap[pos.z];
for(npos.x = pos.x - sightRadius; npos.x <= pos.x + sightRadius; npos.x++) for(npos.x = pos.x - sightRadius; npos.x <= pos.x + sightRadius; npos.x++)
{ {
-14
View File
@@ -26,13 +26,6 @@ struct DLL_EXPORT ResourceObjective
TResources resources; //how many resoures do we need TResources resources; //how many resoures do we need
Goals::TSubgoal goal; //what for (build, gather army etc...) Goals::TSubgoal goal; //what for (build, gather army etc...)
//TODO: register?
template<typename Handler> void serializeInternal(Handler & h)
{
h & resources;
//h & goal; //FIXME: goal serialization is broken
}
}; };
class DLL_EXPORT IResourceManager //: public: IAbstractManager class DLL_EXPORT IResourceManager //: public: IAbstractManager
@@ -103,11 +96,4 @@ private:
boost::heap::binomial_heap<ResourceObjective> queue; boost::heap::binomial_heap<ResourceObjective> queue;
void dumpToLog() const; void dumpToLog() const;
//TODO: register?
template<typename Handler> void serializeInternal(Handler & h)
{
h & saving;
h & queue;
}
}; };
-25
View File
@@ -747,31 +747,6 @@ void VCAI::showMapObjectSelectDialog(QueryID askID, const Component & icon, cons
requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); }); requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); });
} }
void VCAI::saveGame(BinarySerializer & h)
{
NET_EVENT_HANDLER;
validateVisitableObjs();
#if 0
//disabled due to issue 2890
registerGoals(h);
#endif // 0
CAdventureAI::saveGame(h);
serializeInternal(h);
}
void VCAI::loadGame(BinaryDeserializer & h)
{
//NET_EVENT_HANDLER;
#if 0
//disabled due to issue 2890
registerGoals(h);
#endif // 0
CAdventureAI::loadGame(h);
serializeInternal(h);
}
void makePossibleUpgrades(const CArmedInstance * obj) void makePossibleUpgrades(const CArmedInstance * obj)
{ {
if(!obj) if(!obj)
-97
View File
@@ -66,15 +66,6 @@ public:
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID); void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
void receivedAnswerConfirmation(int answerRequestID, int result); void receivedAnswerConfirmation(int answerRequestID, int result);
void heroVisit(const CGObjectInstance * obj, bool started); void heroVisit(const CGObjectInstance * obj, bool started);
template<typename Handler> void serialize(Handler & h)
{
h & battle;
h & remainingQueries;
h & requestToQueryID;
h & havingTurn;
}
}; };
class DLL_EXPORT VCAI : public CAdventureAI class DLL_EXPORT VCAI : public CAdventureAI
@@ -152,8 +143,6 @@ public:
void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override; void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override; void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
void saveGame(BinarySerializer & h) override; //saving
void loadGame(BinaryDeserializer & h) override; //loading
void finish() override; void finish() override;
void availableCreaturesChanged(const CGDwelling * town) override; void availableCreaturesChanged(const CGDwelling * town) override;
@@ -273,92 +262,6 @@ public:
void answerQuery(QueryID queryID, int selection); void answerQuery(QueryID queryID, int selection);
//special function that can be called ONLY from game events handling thread and will send request ASAP //special function that can be called ONLY from game events handling thread and will send request ASAP
void requestActionASAP(std::function<void()> whatToDo); void requestActionASAP(std::function<void()> whatToDo);
#if 0
//disabled due to issue 2890
template<typename Handler> void registerGoals(Handler & h)
{
//h.template registerType<Goals::AbstractGoal, Goals::BoostHero>();
h.template registerType<Goals::AbstractGoal, Goals::Build>();
h.template registerType<Goals::AbstractGoal, Goals::BuildThis>();
//h.template registerType<Goals::AbstractGoal, Goals::CIssueCommand>();
h.template registerType<Goals::AbstractGoal, Goals::ClearWayTo>();
h.template registerType<Goals::AbstractGoal, Goals::CollectRes>();
h.template registerType<Goals::AbstractGoal, Goals::Conquer>();
h.template registerType<Goals::AbstractGoal, Goals::DigAtTile>();
h.template registerType<Goals::AbstractGoal, Goals::Explore>();
h.template registerType<Goals::AbstractGoal, Goals::FindObj>();
h.template registerType<Goals::AbstractGoal, Goals::GatherArmy>();
h.template registerType<Goals::AbstractGoal, Goals::GatherTroops>();
h.template registerType<Goals::AbstractGoal, Goals::GetArtOfType>();
h.template registerType<Goals::AbstractGoal, Goals::VisitObj>();
h.template registerType<Goals::AbstractGoal, Goals::Invalid>();
//h.template registerType<Goals::AbstractGoal, Goals::NotLose>();
h.template registerType<Goals::AbstractGoal, Goals::RecruitHero>();
h.template registerType<Goals::AbstractGoal, Goals::VisitHero>();
h.template registerType<Goals::AbstractGoal, Goals::VisitTile>();
h.template registerType<Goals::AbstractGoal, Goals::Win>();
}
#endif
template<typename Handler> void serializeInternal(Handler & h)
{
h & knownTeleportChannels;
h & knownSubterraneanGates;
h & destinationTeleport;
h & townVisitsThisWeek;
#if 0
//disabled due to issue 2890
h & lockedHeroes;
#else
{
ui32 length = 0;
h & length;
if(!h.saving)
{
std::set<ui32> loadedPointers;
lockedHeroes.clear();
for(ui32 index = 0; index < length; index++)
{
HeroPtr ignored1;
h & ignored1;
ui8 flag = 0;
h & flag;
if(flag)
{
ui32 pid = 0xffffffff;
h & pid;
if(!vstd::contains(loadedPointers, pid))
{
loadedPointers.insert(pid);
ui16 typeId = 0;
//this is the problem requires such hack
//we have to explicitly ignore invalid goal class type id
h & typeId;
Goals::AbstractGoal ignored2;
ignored2.serialize(h);
}
}
}
}
}
#endif
h & reservedHeroesMap; //FIXME: cannot instantiate abstract class
h & visitableObjs;
h & alreadyVisited;
h & reservedObjs;
h & status;
h & battlename;
h & heroesUnableToExplore;
//myCB is restored after load by init call
}
}; };
class cannotFulfillGoalException : public std::exception class cannotFulfillGoalException : public std::exception
-14
View File
@@ -142,7 +142,6 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player):
makingTurn = false; makingTurn = false;
showingDialog = new CondSh<bool>(false); showingDialog = new CondSh<bool>(false);
cingconsole = new CInGameConsole(); cingconsole = new CInGameConsole();
firstCall = 1; //if loading will be overwritten in serialize
autosaveCount = 0; autosaveCount = 0;
isAutoFightOn = false; isAutoFightOn = false;
isAutoFightEndBattle = false; isAutoFightEndBattle = false;
@@ -1201,19 +1200,6 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
} }
} }
void CPlayerInterface::saveGame( BinarySerializer & h )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
localState->serialize(h);
}
void CPlayerInterface::loadGame( BinaryDeserializer & h )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
localState->serialize(h);
firstCall = -1;
}
void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path ) void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path )
{ {
assert(h); assert(h);
-4
View File
@@ -61,8 +61,6 @@ class CPlayerInterface : public CGameInterface, public IUpdateable
bool ignoreEvents; bool ignoreEvents;
size_t numOfMovedArts; size_t numOfMovedArts;
// -1 - just loaded game; 1 - just started game; 0 otherwise
int firstCall;
int autosaveCount; int autosaveCount;
std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!) std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
@@ -146,8 +144,6 @@ protected: // Call-ins from server, should not be called directly, but only via
void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override; void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
void playerEndsTurn(PlayerColor player) override; void playerEndsTurn(PlayerColor player) override;
void saveGame(BinarySerializer & h) override; //saving
void loadGame(BinaryDeserializer & h) override; //loading
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override; void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
//for battles //for battles
+2 -130
View File
@@ -203,137 +203,9 @@ void CClient::loadGame(CGameState * initializedGameState)
reinitScripting(); reinitScripting();
initPlayerEnvironments(); initPlayerEnvironments();
// Loading of client state - disabled for now
// Since client no longer writes or loads its own state and instead receives it from server
// client state serializer will serialize its own copies of all pointers, e.g. heroes/towns/objects
// and on deserialize will create its own copies (instead of using copies from state received from server)
// Potential solutions:
// 1) Use server gamestate to deserialize pointers, so any pointer to same object will point to server instance and not our copy
// 2) Remove all serialization of pointers with instance ID's and restore them on load (including AI deserializer code)
// 3) Completely remove client savegame and send all information, like hero paths and sleeping status to server (either in form of hero properties or as some generic "client options" message
#ifdef BROKEN_CLIENT_STATE_SERIALIZATION_HAS_BEEN_FIXED
// try to deserialize client data including sleepingHeroes
try
{
boost::filesystem::path clientSaveName = *CResourceHandler::get()->getResourceName(ResourcePath(CSH->si->mapname, EResType::CLIENT_SAVEGAME));
if(clientSaveName.empty())
throw std::runtime_error("Cannot open client part of " + CSH->si->mapname);
std::unique_ptr<CLoadFile> loader (new CLoadFile(clientSaveName));
serialize(loader->serializer, loader->serializer.version);
logNetwork->info("Client data loaded.");
}
catch(std::exception & e)
{
logGlobal->info("Cannot load client data for game %s. Error: %s", CSH->si->mapname, e.what());
}
#endif
initPlayerInterfaces(); initPlayerInterfaces();
} }
void CClient::serialize(BinarySerializer & h)
{
assert(h.saving);
ui8 players = static_cast<ui8>(playerint.size());
h & players;
for(auto i = playerint.begin(); i != playerint.end(); i++)
{
logGlobal->trace("Saving player %s interface", i->first);
assert(i->first == i->second->playerID);
h & i->first;
h & i->second->dllName;
h & i->second->human;
i->second->saveGame(h);
}
#if SCRIPTING_ENABLED
JsonNode scriptsState;
clientScripts->serializeState(h.saving, scriptsState);
h & scriptsState;
#endif
}
void CClient::serialize(BinaryDeserializer & h)
{
assert(!h.saving);
ui8 players = 0;
h & players;
for(int i = 0; i < players; i++)
{
std::string dllname;
PlayerColor pid;
bool isHuman = false;
auto prevInt = LOCPLINT;
h & pid;
h & dllname;
h & isHuman;
assert(dllname.length() == 0 || !isHuman);
if(pid == PlayerColor::NEUTRAL)
{
logGlobal->trace("Neutral battle interfaces are not serialized.");
continue;
}
logGlobal->trace("Loading player %s interface", pid);
std::shared_ptr<CGameInterface> nInt;
if(dllname.length())
nInt = CDynLibHandler::getNewAI(dllname);
else
nInt = std::make_shared<CPlayerInterface>(pid);
nInt->dllName = dllname;
nInt->human = isHuman;
nInt->playerID = pid;
bool shouldResetInterface = true;
// Client no longer handle this player at all
if(!vstd::contains(CSH->getAllClientPlayers(CSH->logicConnection->connectionID), pid))
{
logGlobal->trace("Player %s is not belong to this client. Destroying interface", pid);
}
else if(isHuman && !vstd::contains(CSH->getHumanColors(), pid))
{
logGlobal->trace("Player %s is no longer controlled by human. Destroying interface", pid);
}
else if(!isHuman && vstd::contains(CSH->getHumanColors(), pid))
{
logGlobal->trace("Player %s is no longer controlled by AI. Destroying interface", pid);
}
else
{
installNewPlayerInterface(nInt, pid);
shouldResetInterface = false;
}
// loadGame needs to be called after initGameInterface to load paths correctly
// initGameInterface is called in installNewPlayerInterface
nInt->loadGame(h);
if (shouldResetInterface)
{
nInt.reset();
LOCPLINT = prevInt;
}
}
#if SCRIPTING_ENABLED
{
JsonNode scriptsState;
h & scriptsState;
clientScripts->serializeState(h.saving, scriptsState);
}
#endif
logNetwork->trace("Loaded client part of save %d ms", CSH->th->getDiff());
}
void CClient::save(const std::string & fname) void CClient::save(const std::string & fname)
{ {
if(!gs->currentBattles.empty()) if(!gs->currentBattles.empty())
@@ -460,7 +332,7 @@ void CClient::initPlayerInterfaces()
logNetwork->trace("Initialized player interfaces %d ms", CSH->th->getDiff()); logNetwork->trace("Initialized player interfaces %d ms", CSH->th->getDiff());
} }
std::string CClient::aiNameForPlayer(const PlayerSettings & ps, bool battleAI, bool alliedToHuman) std::string CClient::aiNameForPlayer(const PlayerSettings & ps, bool battleAI, bool alliedToHuman) const
{ {
if(ps.name.size()) if(ps.name.size())
{ {
@@ -472,7 +344,7 @@ std::string CClient::aiNameForPlayer(const PlayerSettings & ps, bool battleAI, b
return aiNameForPlayer(battleAI, alliedToHuman); return aiNameForPlayer(battleAI, alliedToHuman);
} }
std::string CClient::aiNameForPlayer(bool battleAI, bool alliedToHuman) std::string CClient::aiNameForPlayer(bool battleAI, bool alliedToHuman) const
{ {
const int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I; const int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I;
std::string goodAdventureAI = alliedToHuman ? settings["server"]["alliedAI"].String() : settings["server"]["playerAI"].String(); std::string goodAdventureAI = alliedToHuman ? settings["server"]["alliedAI"].String() : settings["server"]["playerAI"].String();
+2 -4
View File
@@ -131,8 +131,6 @@ public:
void newGame(CGameState * gameState); void newGame(CGameState * gameState);
void loadGame(CGameState * gameState); void loadGame(CGameState * gameState);
void serialize(BinarySerializer & h);
void serialize(BinaryDeserializer & h);
void save(const std::string & fname); void save(const std::string & fname);
void endGame(); void endGame();
@@ -140,8 +138,8 @@ public:
void initMapHandler(); void initMapHandler();
void initPlayerEnvironments(); void initPlayerEnvironments();
void initPlayerInterfaces(); void initPlayerInterfaces();
std::string aiNameForPlayer(const PlayerSettings & ps, bool battleAI, bool alliedToHuman); //empty means no AI -> human std::string aiNameForPlayer(const PlayerSettings & ps, bool battleAI, bool alliedToHuman) const; //empty means no AI -> human
std::string aiNameForPlayer(bool battleAI, bool alliedToHuman); std::string aiNameForPlayer(bool battleAI, bool alliedToHuman) const;
void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, PlayerColor color, bool battlecb = false); void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, PlayerColor color, bool battlecb = false);
void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, PlayerColor color, bool needCallback = true); void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, PlayerColor color, bool needCallback = true);
-27
View File
@@ -45,15 +45,6 @@ public:
int spellbookLastPageAdvmap = 0; int spellbookLastPageAdvmap = 0;
int spellbookLastTabBattle = 4; int spellbookLastTabBattle = 4;
int spellbookLastTabAdvmap = 4; int spellbookLastTabAdvmap = 4;
template<typename Handler>
void serialize(Handler & h)
{
h & spellbookLastPageBattle;
h & spellbookLastPageAdvmap;
h & spellbookLastTabBattle;
h & spellbookLastTabAdvmap;
}
} spellbookSettings; } spellbookSettings;
explicit PlayerLocalState(CPlayerInterface & owner); explicit PlayerLocalState(CPlayerInterface & owner);
@@ -92,22 +83,4 @@ public:
/// Changes currently selected object /// Changes currently selected object
void setSelection(const CArmedInstance *sel); void setSelection(const CArmedInstance *sel);
template<typename Handler>
void serialize(Handler & h)
{
//WARNING: this code is broken and not used. See CClient::loadGame
std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
if(h.saving)
saveHeroPaths(pathsMap);
h & pathsMap;
if(!h.saving)
loadHeroPaths(pathsMap);
h & ownedTowns;
h & wanderingHeroes;
h & sleepingHeroes;
}
}; };
+2 -1
View File
@@ -16,6 +16,7 @@
#include "bonuses/CBonusSystemNode.h" #include "bonuses/CBonusSystemNode.h"
#include "GameConstants.h" #include "GameConstants.h"
#include "IHandlerBase.h" #include "IHandlerBase.h"
#include "serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -187,7 +188,7 @@ struct DLL_LINKAGE ArtSlotInfo
} }
}; };
class DLL_LINKAGE CArtifactSet class DLL_LINKAGE CArtifactSet : public virtual Serializeable
{ {
public: public:
using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>; using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>;
+2 -1
View File
@@ -11,6 +11,7 @@
#include "bonuses/Bonus.h" #include "bonuses/Bonus.h"
#include "bonuses/CBonusSystemNode.h" #include "bonuses/CBonusSystemNode.h"
#include "serializer/Serializeable.h"
#include "GameConstants.h" #include "GameConstants.h"
#include "CArtHandler.h" #include "CArtHandler.h"
#include "CArtifactInstance.h" #include "CArtifactInstance.h"
@@ -208,7 +209,7 @@ namespace NArmyFormation
static const std::vector<std::string> names{ "wide", "tight" }; static const std::vector<std::string> names{ "wide", "tight" };
} }
class DLL_LINKAGE CCreatureSet : public IArmyDescriptor //seven combined creatures class DLL_LINKAGE CCreatureSet : public IArmyDescriptor, public virtual Serializeable //seven combined creatures
{ {
CCreatureSet(const CCreatureSet &) = delete; CCreatureSet(const CCreatureSet &) = delete;
CCreatureSet &operator=(const CCreatureSet&); CCreatureSet &operator=(const CCreatureSet&);
+1 -1
View File
@@ -553,7 +553,7 @@ std::shared_ptr<const boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::ge
for(tile.x = 0; tile.x < width; tile.x++) for(tile.x = 0; tile.x < width; tile.x++)
for(tile.y = 0; tile.y < height; tile.y++) for(tile.y = 0; tile.y < height; tile.y++)
{ {
if ((*team->fogOfWarMap)[tile.z][tile.x][tile.y]) if (team->fogOfWarMap[tile.z][tile.x][tile.y])
(*ptr)[tile.z][tile.x][tile.y] = &gs->map->getTile(tile); (*ptr)[tile.z][tile.x][tile.y] = &gs->map->getTile(tile);
else else
(*ptr)[tile.z][tile.x][tile.y] = nullptr; (*ptr)[tile.z][tile.x][tile.y] = nullptr;
-24
View File
@@ -243,28 +243,4 @@ void CAdventureAI::yourTacticPhase(const BattleID & battleID, int distance)
battleAI->yourTacticPhase(battleID, distance); battleAI->yourTacticPhase(battleID, distance);
} }
void CAdventureAI::saveGame(BinarySerializer & h) /*saving */
{
bool hasBattleAI = static_cast<bool>(battleAI);
h & hasBattleAI;
if(hasBattleAI)
{
h & battleAI->dllName;
}
}
void CAdventureAI::loadGame(BinaryDeserializer & h) /*loading */
{
bool hasBattleAI = false;
h & hasBattleAI;
if(hasBattleAI)
{
std::string dllName;
h & dllName;
battleAI = CDynLibHandler::getNewBattleAI(dllName);
assert(cbc); //it should have been set by the one who new'ed us
battleAI->initBattleInterface(env, cbc);
}
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
-6
View File
@@ -110,9 +110,6 @@ public:
virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain){}; virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain){};
virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) = 0; virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) = 0;
virtual void saveGame(BinarySerializer & h) = 0;
virtual void loadGame(BinaryDeserializer & h) = 0;
}; };
class DLL_LINKAGE CDynLibHandler class DLL_LINKAGE CDynLibHandler
@@ -161,9 +158,6 @@ public:
void battleSpellCast(const BattleID & battleID, const BattleSpellCast *sc) override; void battleSpellCast(const BattleID & battleID, const BattleSpellCast *sc) override;
void battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID) override; void battleEnd(const BattleID & battleID, const BattleResult *br, QueryID queryID) override;
void battleUnitsChanged(const BattleID & battleID, const std::vector<UnitChanges> & units) override; void battleUnitsChanged(const BattleID & battleID, const std::vector<UnitChanges> & units) override;
void saveGame(BinarySerializer & h) override;
void loadGame(BinaryDeserializer & h) override;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
+20 -13
View File
@@ -196,24 +196,31 @@ public:
template <typename Handler> template <typename Handler>
void serialize(Handler & h) void serialize(Handler & h)
{ {
std::string key; if (h.version >= Handler::Version::SIMPLE_TEXT_CONTAINER_SERIALIZATION)
auto sz = stringsLocalizations.size();
h & sz;
if(h.saving)
{ {
for(auto s : stringsLocalizations) h & stringsLocalizations;
{
key = s.first;
h & key;
h & s.second;
}
} }
else else
{ {
for(size_t i = 0; i < sz; ++i) std::string key;
int64_t sz = stringsLocalizations.size();
h & sz;
if(h.saving)
{ {
h & key; for(auto s : stringsLocalizations)
h & stringsLocalizations[key]; {
key = s.first;
h & key;
h & s.second;
}
}
else
{
for(size_t i = 0; i < sz; ++i)
{
h & key;
h & stringsLocalizations[key];
}
} }
} }
} }
+1
View File
@@ -602,6 +602,7 @@ set(lib_MAIN_HEADERS
serializer/JsonUpdater.h serializer/JsonUpdater.h
serializer/Cast.h serializer/Cast.h
serializer/ESerializationVersion.h serializer/ESerializationVersion.h
serializer/Serializeable.h
spells/AbilityCaster.h spells/AbilityCaster.h
spells/AdventureSpellMechanics.h spells/AdventureSpellMechanics.h
+13 -1
View File
@@ -128,7 +128,7 @@ public:
TeamID id; //position in gameState::teams TeamID id; //position in gameState::teams
std::set<PlayerColor> players; // members of this team std::set<PlayerColor> players; // members of this team
//TODO: boost::array, bool if possible //TODO: boost::array, bool if possible
std::unique_ptr<boost::multi_array<ui8, 3>> fogOfWarMap; //[z][x][y] true - visible, false - hidden boost::multi_array<ui8, 3> fogOfWarMap; //[z][x][y] true - visible, false - hidden
TeamState(); TeamState();
@@ -136,6 +136,18 @@ public:
{ {
h & id; h & id;
h & players; h & players;
if (h.version < Handler::Version::REMOVE_FOG_OF_WAR_POINTER)
{
struct Helper : public Serializeable
{
void serialize(Handler &h)
{}
};
Helper helper;
auto ptrHelper = &helper;
h & ptrHelper;
}
h & fogOfWarMap; h & fogOfWarMap;
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
} }
+2 -1
View File
@@ -11,6 +11,7 @@
#pragma once #pragma once
#include <vstd/RNG.h> #include <vstd/RNG.h>
#include "serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -27,7 +28,7 @@ using TRandI = std::function<int()>;
/// The random generator randomly generates integers and real numbers("doubles") between /// The random generator randomly generates integers and real numbers("doubles") between
/// a given range. This is a header only class and mainly a wrapper for /// a given range. This is a header only class and mainly a wrapper for
/// convenient usage of the standard random API. An instance of this RNG is not thread safe. /// convenient usage of the standard random API. An instance of this RNG is not thread safe.
class DLL_LINKAGE CRandomGenerator : public vstd::RNG, boost::noncopyable class DLL_LINKAGE CRandomGenerator : public vstd::RNG, boost::noncopyable, public Serializeable
{ {
public: public:
/// Seeds the generator by default with the product of the current time in milliseconds and the /// Seeds the generator by default with the product of the current time in milliseconds and the
+2 -2
View File
@@ -103,8 +103,8 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3> & tiles,
if(distance <= radious) if(distance <= radious)
{ {
if(!player if(!player
|| (mode == ETileVisibility::HIDDEN && (*team->fogOfWarMap)[pos.z][xd][yd] == 0) || (mode == ETileVisibility::HIDDEN && team->fogOfWarMap[pos.z][xd][yd] == 0)
|| (mode == ETileVisibility::REVEALED && (*team->fogOfWarMap)[pos.z][xd][yd] == 1) || (mode == ETileVisibility::REVEALED && team->fogOfWarMap[pos.z][xd][yd] == 1)
) )
tiles.insert(int3(xd,yd,pos.z)); tiles.insert(int3(xd,yd,pos.z));
} }
+2 -1
View File
@@ -15,6 +15,7 @@
#include "TurnTimerInfo.h" #include "TurnTimerInfo.h"
#include "ExtraOptionsInfo.h" #include "ExtraOptionsInfo.h"
#include "campaign/CampaignConstants.h" #include "campaign/CampaignConstants.h"
#include "serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -107,7 +108,7 @@ enum class EStartMode : int32_t
}; };
/// Struct which describes the difficulty, the turn time,.. of a heroes match. /// Struct which describes the difficulty, the turn time,.. of a heroes match.
struct DLL_LINKAGE StartInfo struct DLL_LINKAGE StartInfo : public Serializeable
{ {
EStartMode mode; EStartMode mode;
ui8 difficulty; //0=easy; 4=impossible ui8 difficulty; //0=easy; 4=impossible
+4 -2
View File
@@ -9,9 +9,11 @@
*/ */
#pragma once #pragma once
#include "BattleHex.h" #include "BattleHex.h"
#include "../constants/EntityIdentifiers.h"
#include "../filesystem/ResourcePath.h" #include "../filesystem/ResourcePath.h"
#include "../networkPacks/BattleChanges.h" #include "../networkPacks/BattleChanges.h"
#include "../constants/EntityIdentifiers.h" #include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -20,7 +22,7 @@ class ObstacleChanges;
class JsonSerializeFormat; class JsonSerializeFormat;
class SpellID; class SpellID;
struct DLL_LINKAGE CObstacleInstance struct DLL_LINKAGE CObstacleInstance : public Serializeable
{ {
enum EObstacleType : ui8 enum EObstacleType : ui8
{ {
+2 -1
View File
@@ -13,6 +13,7 @@
#include "BonusCustomTypes.h" #include "BonusCustomTypes.h"
#include "../constants/VariantIdentifier.h" #include "../constants/VariantIdentifier.h"
#include "../constants/EntityIdentifiers.h" #include "../constants/EntityIdentifiers.h"
#include "../serializer/Serializeable.h"
#include "../MetaString.h" #include "../MetaString.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -55,7 +56,7 @@ public:
#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix(); #define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();
/// Struct for handling bonuses of several types. Can be transferred to any hero /// Struct for handling bonuses of several types. Can be transferred to any hero
struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus> struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Serializeable
{ {
BonusDuration::Type duration = BonusDuration::PERMANENT; //uses BonusDuration values BonusDuration::Type duration = BonusDuration::PERMANENT; //uses BonusDuration values
si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
+3 -3
View File
@@ -9,11 +9,11 @@
*/ */
#pragma once #pragma once
#include "GameConstants.h"
#include "BonusList.h" #include "BonusList.h"
#include "IBonusBearer.h" #include "IBonusBearer.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
using TNodes = std::set<CBonusSystemNode *>; using TNodes = std::set<CBonusSystemNode *>;
@@ -21,7 +21,7 @@ using TCNodes = std::set<const CBonusSystemNode *>;
using TNodesVector = std::vector<CBonusSystemNode *>; using TNodesVector = std::vector<CBonusSystemNode *>;
using TCNodesVector = std::vector<const CBonusSystemNode *>; using TCNodesVector = std::vector<const CBonusSystemNode *>;
class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public boost::noncopyable class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public virtual Serializeable, public boost::noncopyable
{ {
public: public:
enum ENodeTypes enum ENodeTypes
+3 -2
View File
@@ -10,8 +10,9 @@
#include "Bonus.h" #include "Bonus.h"
#include "../GameConstants.h"
#include "../battle/BattleHex.h" #include "../battle/BattleHex.h"
#include "../serializer/Serializeable.h"
#include "../constants/Enumerations.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -27,7 +28,7 @@ struct BonusLimitationContext
const BonusList & stillUndecided; const BonusList & stillUndecided;
}; };
class DLL_LINKAGE ILimiter class DLL_LINKAGE ILimiter : public Serializeable
{ {
public: public:
enum class EDecision : uint8_t {ACCEPT, DISCARD, NOT_SURE}; enum class EDecision : uint8_t {ACCEPT, DISCARD, NOT_SURE};
+4 -2
View File
@@ -12,11 +12,13 @@
#include "Bonus.h" #include "Bonus.h"
#include "CBonusSystemNode.h" #include "CBonusSystemNode.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
extern DLL_LINKAGE const std::map<std::string, TPropagatorPtr> bonusPropagatorMap; extern DLL_LINKAGE const std::map<std::string, TPropagatorPtr> bonusPropagatorMap;
class DLL_LINKAGE IPropagator class DLL_LINKAGE IPropagator : public Serializeable
{ {
public: public:
virtual ~IPropagator() = default; virtual ~IPropagator() = default;
@@ -42,4 +44,4 @@ public:
} }
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
+3 -2
View File
@@ -10,6 +10,7 @@
#pragma once #pragma once
#include "Bonus.h" #include "Bonus.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -17,7 +18,7 @@ extern DLL_LINKAGE const std::map<std::string, TUpdaterPtr> bonusUpdaterMap;
// observers for updating bonuses based on certain events (e.g. hero gaining level) // observers for updating bonuses based on certain events (e.g. hero gaining level)
class DLL_LINKAGE IUpdater class DLL_LINKAGE IUpdater : public Serializeable
{ {
public: public:
virtual ~IUpdater() = default; virtual ~IUpdater() = default;
@@ -114,4 +115,4 @@ public:
JsonNode toJsonNode() const override; JsonNode toJsonNode() const override;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
+2 -1
View File
@@ -12,6 +12,7 @@
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../MetaString.h" #include "../MetaString.h"
#include "../filesystem/ResourcePath.h" #include "../filesystem/ResourcePath.h"
#include "../serializer/Serializeable.h"
#include "../CGeneralTextHandler.h" #include "../CGeneralTextHandler.h"
#include "CampaignConstants.h" #include "CampaignConstants.h"
#include "CampaignScenarioPrologEpilog.h" #include "CampaignScenarioPrologEpilog.h"
@@ -214,7 +215,7 @@ struct DLL_LINKAGE CampaignScenario
}; };
/// Class that represents loaded campaign information /// Class that represents loaded campaign information
class DLL_LINKAGE Campaign : public CampaignHeader class DLL_LINKAGE Campaign : public CampaignHeader, public Serializeable
{ {
friend class CampaignHandler; friend class CampaignHandler;
+4 -5
View File
@@ -693,8 +693,8 @@ void CGameState::initFogOfWar()
for(auto & elem : teams) for(auto & elem : teams)
{ {
auto & fow = elem.second.fogOfWarMap; auto & fow = elem.second.fogOfWarMap;
fow->resize(boost::extents[layers][map->width][map->height]); fow.resize(boost::extents[layers][map->width][map->height]);
std::fill(fow->data(), fow->data() + fow->num_elements(), 0); std::fill(fow.data(), fow.data() + fow.num_elements(), 0);
for(CGObjectInstance *obj : map->objects) for(CGObjectInstance *obj : map->objects)
{ {
@@ -704,7 +704,7 @@ void CGameState::initFogOfWar()
getTilesInRange(tiles, obj->getSightCenter(), obj->getSightRadius(), ETileVisibility::HIDDEN, obj->tempOwner); getTilesInRange(tiles, obj->getSightCenter(), obj->getSightRadius(), ETileVisibility::HIDDEN, obj->tempOwner);
for(const int3 & tile : tiles) for(const int3 & tile : tiles)
{ {
(*elem.second.fogOfWarMap)[tile.z][tile.x][tile.y] = 1; elem.second.fogOfWarMap[tile.z][tile.x][tile.y] = 1;
} }
} }
} }
@@ -1326,7 +1326,7 @@ bool CGameState::isVisible(int3 pos, const std::optional<PlayerColor> & player)
if(player->isSpectator()) if(player->isSpectator())
return true; return true;
return (*getPlayerTeam(*player)->fogOfWarMap)[pos.z][pos.x][pos.y]; return getPlayerTeam(*player)->fogOfWarMap[pos.z][pos.x][pos.y];
} }
bool CGameState::isVisible(const CGObjectInstance * obj, const std::optional<PlayerColor> & player) const bool CGameState::isVisible(const CGObjectInstance * obj, const std::optional<PlayerColor> & player) const
@@ -1957,7 +1957,6 @@ bool RumorState::update(int id, int extra)
TeamState::TeamState() TeamState::TeamState()
{ {
setNodeType(TEAM); setNodeType(TEAM);
fogOfWarMap = std::make_unique<boost::multi_array<ui8, 3>>();
} }
CRandomGenerator & CGameState::getRandomGenerator() CRandomGenerator & CGameState::getRandomGenerator()
+1 -1
View File
@@ -79,7 +79,7 @@ class BattleInfo;
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult); DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult);
class DLL_LINKAGE CGameState : public CNonConstInfoCallback class DLL_LINKAGE CGameState : public CNonConstInfoCallback, public Serializeable
{ {
friend class CGameStateCampaign; friend class CGameStateCampaign;
+2 -1
View File
@@ -11,6 +11,7 @@
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../campaign/CampaignConstants.h" #include "../campaign/CampaignConstants.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -28,7 +29,7 @@ struct CampaignHeroReplacement
std::vector<ArtifactPosition> transferrableArtifacts; std::vector<ArtifactPosition> transferrableArtifacts;
}; };
class CGameStateCampaign class CGameStateCampaign : public Serializeable
{ {
CGameState * gameState; CGameState * gameState;
+3 -1
View File
@@ -11,6 +11,8 @@
#include "../GameConstants.h" #include "../GameConstants.h"
#include "TavernSlot.h" #include "TavernSlot.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -21,7 +23,7 @@ class CHeroClass;
class CGameState; class CGameState;
class CSimpleArmy; class CSimpleArmy;
class DLL_LINKAGE TavernHeroesPool class DLL_LINKAGE TavernHeroesPool : public Serializeable
{ {
struct TavernSlot struct TavernSlot
{ {
@@ -16,10 +16,11 @@
#include "../ResourceSet.h" #include "../ResourceSet.h"
#include "../json/JsonNode.h" #include "../json/JsonNode.h"
#include "../mapObjects/CBank.h" #include "../mapObjects/CBank.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
struct BankConfig struct BankConfig : public Serializeable
{ {
ui32 chance = 0; //chance for this level being chosen ui32 chance = 0; //chance for this level being chosen
std::vector<CStackBasicDescriptor> guards; //creature ID, amount std::vector<CStackBasicDescriptor> guards; //creature ID, amount
+1 -1
View File
@@ -270,7 +270,7 @@ void CGCreature::initObj(CRandomGenerator & rand)
} }
} }
temppower = stacks[SlotID(0)]->count * static_cast<ui64>(1000); temppower = stacks[SlotID(0)]->count * static_cast<int64_t>(1000);
refusedJoining = false; refusedJoining = false;
} }
+1 -1
View File
@@ -35,7 +35,7 @@ public:
ArtifactID gainedArtifact; //ID of artifact gained to hero, -1 if none ArtifactID gainedArtifact; //ID of artifact gained to hero, -1 if none
bool neverFlees = false; //if true, the troops will never flee bool neverFlees = false; //if true, the troops will never flee
bool notGrowingTeam = false; //if true, number of units won't grow bool notGrowingTeam = false; //if true, number of units won't grow
ui64 temppower = 0; //used to handle fractional stack growth for tiny stacks int64_t temppower = 0; //used to handle fractional stack growth for tiny stacks
bool refusedJoining = false; bool refusedJoining = false;
+2 -1
View File
@@ -10,10 +10,11 @@
#pragma once #pragma once
#include "IObjectInterface.h" #include "IObjectInterface.h"
#include "../bonuses/BonusEnum.h"
#include "../constants/EntityIdentifiers.h" #include "../constants/EntityIdentifiers.h"
#include "../filesystem/ResourcePath.h" #include "../filesystem/ResourcePath.h"
#include "../int3.h" #include "../int3.h"
#include "../bonuses/BonusEnum.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
+10 -9
View File
@@ -12,6 +12,7 @@
#include "CRewardableObject.h" #include "CRewardableObject.h"
#include "../ResourceSet.h" #include "../ResourceSet.h"
#include "../MetaString.h" #include "../MetaString.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -36,7 +37,7 @@ enum class EQuestMission {
HOTA_REACH_DATE = 13, HOTA_REACH_DATE = 13,
}; };
class DLL_LINKAGE CQuest final class DLL_LINKAGE CQuest final : public Serializeable
{ {
public: public:
@@ -74,13 +75,13 @@ public:
CQuest(); //TODO: Remove constructor CQuest(); //TODO: Remove constructor
static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army); static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army);
virtual bool checkQuest(const CGHeroInstance * h) const; //determines whether the quest is complete or not bool checkQuest(const CGHeroInstance * h) const; //determines whether the quest is complete or not
virtual void getVisitText(IGameCallback * cb, MetaString &text, std::vector<Component> & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const; void getVisitText(IGameCallback * cb, MetaString &text, std::vector<Component> & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
virtual void getCompletionText(IGameCallback * cb, MetaString &text) const; void getCompletionText(IGameCallback * cb, MetaString &text) const;
virtual void getRolloverText (IGameCallback * cb, MetaString &text, bool onHover) const; //hover or quest log entry void getRolloverText (IGameCallback * cb, MetaString &text, bool onHover) const; //hover or quest log entry
virtual void completeQuest(IGameCallback *, const CGHeroInstance * h) const; void completeQuest(IGameCallback *, const CGHeroInstance * h) const;
virtual void addTextReplacements(IGameCallback * cb, MetaString &out, std::vector<Component> & components) const; void addTextReplacements(IGameCallback * cb, MetaString &out, std::vector<Component> & components) const;
virtual void addKillTargetReplacements(MetaString &out) const; void addKillTargetReplacements(MetaString &out) const;
void defineQuestName(); void defineQuestName();
bool operator== (const CQuest & quest) const bool operator== (const CQuest & quest) const
@@ -114,7 +115,7 @@ public:
void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName); void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName);
}; };
class DLL_LINKAGE IQuestObject class DLL_LINKAGE IQuestObject : public virtual Serializeable
{ {
public: public:
CQuest * quest = new CQuest(); CQuest * quest = new CQuest();
+4 -3
View File
@@ -9,10 +9,11 @@
*/ */
#pragma once #pragma once
#include "../GameCallbackHolder.h"
#include "../constants/EntityIdentifiers.h"
#include "../networkPacks/EInfoWindowMode.h" #include "../networkPacks/EInfoWindowMode.h"
#include "../networkPacks/ObjProperty.h" #include "../networkPacks/ObjProperty.h"
#include "../constants/EntityIdentifiers.h" #include "../serializer/Serializeable.h"
#include "../GameCallbackHolder.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -29,7 +30,7 @@ class int3;
class MetaString; class MetaString;
class PlayerColor; class PlayerColor;
class DLL_LINKAGE IObjectInterface : public GameCallbackHolder class DLL_LINKAGE IObjectInterface : public GameCallbackHolder, public virtual Serializeable
{ {
public: public:
using GameCallbackHolder::GameCallbackHolder; using GameCallbackHolder::GameCallbackHolder;
+1 -1
View File
@@ -185,7 +185,7 @@ protected:
void serializeJsonOptions(JsonSerializeFormat & handler) override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
}; };
struct DLL_LINKAGE TeleportChannel struct DLL_LINKAGE TeleportChannel : public Serializeable
{ {
enum EPassability {UNKNOWN, IMPASSABLE, PASSABLE}; enum EPassability {UNKNOWN, IMPASSABLE, PASSABLE};
-48
View File
@@ -59,54 +59,6 @@ ObjectTemplate::ObjectTemplate():
{ {
} }
ObjectTemplate::ObjectTemplate(const ObjectTemplate& other):
visitDir(other.visitDir),
allowedTerrains(other.allowedTerrains),
id(other.id),
subid(other.subid),
printPriority(other.printPriority),
animationFile(other.animationFile),
editorAnimationFile(other.editorAnimationFile),
stringID(other.stringID),
width(other.width),
height(other.height),
visitable(other.visitable),
blockedOffsets(other.blockedOffsets),
blockMapOffset(other.blockMapOffset),
visitableOffset(other.visitableOffset)
{
//default copy constructor is failing with usedTiles this for unknown reason
usedTiles.resize(other.usedTiles.size());
for(size_t i = 0; i < usedTiles.size(); i++)
std::copy(other.usedTiles[i].begin(), other.usedTiles[i].end(), std::back_inserter(usedTiles[i]));
}
ObjectTemplate & ObjectTemplate::operator=(const ObjectTemplate & rhs)
{
visitDir = rhs.visitDir;
allowedTerrains = rhs.allowedTerrains;
id = rhs.id;
subid = rhs.subid;
printPriority = rhs.printPriority;
animationFile = rhs.animationFile;
editorAnimationFile = rhs.editorAnimationFile;
stringID = rhs.stringID;
width = rhs.width;
height = rhs.height;
visitable = rhs.visitable;
blockedOffsets = rhs.blockedOffsets;
blockMapOffset = rhs.blockMapOffset;
visitableOffset = rhs.visitableOffset;
usedTiles.clear();
usedTiles.resize(rhs.usedTiles.size());
for(size_t i = 0; i < usedTiles.size(); i++)
std::copy(rhs.usedTiles[i].begin(), rhs.usedTiles[i].end(), std::back_inserter(usedTiles[i]));
return *this;
}
void ObjectTemplate::afterLoadFixup() void ObjectTemplate::afterLoadFixup()
{ {
if(id == Obj::EVENT) if(id == Obj::EVENT)
+2 -5
View File
@@ -12,6 +12,7 @@
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../int3.h" #include "../int3.h"
#include "../filesystem/ResourcePath.h" #include "../filesystem/ResourcePath.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -20,7 +21,7 @@ class CLegacyConfigParser;
class JsonNode; class JsonNode;
class int3; class int3;
class DLL_LINKAGE ObjectTemplate class DLL_LINKAGE ObjectTemplate : public Serializeable
{ {
enum EBlockMapBits enum EBlockMapBits
{ {
@@ -122,10 +123,6 @@ public:
bool canBePlacedAt(TerrainId terrain) const; bool canBePlacedAt(TerrainId terrain) const;
ObjectTemplate(); ObjectTemplate();
//custom copy constructor is required
ObjectTemplate(const ObjectTemplate & other);
ObjectTemplate& operator=(const ObjectTemplate & rhs);
void readTxt(CLegacyConfigParser & parser); void readTxt(CLegacyConfigParser & parser);
void readMsk(); void readMsk();
+3 -2
View File
@@ -13,7 +13,8 @@
#include "../constants/EntityIdentifiers.h" #include "../constants/EntityIdentifiers.h"
#include "../constants/Enumerations.h" #include "../constants/Enumerations.h"
#include "../constants/VariantIdentifier.h" #include "../constants/VariantIdentifier.h"
#include "../modding/CModInfo.h" #include "../modding/ModVerificationInfo.h"
#include "../serializer/Serializeable.h"
#include "../LogicalExpression.h" #include "../LogicalExpression.h"
#include "../int3.h" #include "../int3.h"
#include "../MetaString.h" #include "../MetaString.h"
@@ -202,7 +203,7 @@ enum class EMapDifficulty : uint8_t
}; };
/// The map header holds information about loss/victory condition,map format, version, players, height, width,... /// The map header holds information about loss/victory condition,map format, version, players, height, width,...
class DLL_LINKAGE CMapHeader class DLL_LINKAGE CMapHeader: public Serializeable
{ {
void setupEvents(); void setupEvents();
public: public:
+3 -1
View File
@@ -9,6 +9,8 @@
*/ */
#pragma once #pragma once
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
struct StartInfo; struct StartInfo;
@@ -21,7 +23,7 @@ class ResourcePath;
* A class which stores the count of human players and all players, the filename, * A class which stores the count of human players and all players, the filename,
* scenario options, the map header information,... * scenario options, the map header information,...
*/ */
class DLL_LINKAGE CMapInfo class DLL_LINKAGE CMapInfo : public Serializeable
{ {
public: public:
std::unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign std::unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign
+2 -1
View File
@@ -10,6 +10,7 @@
#pragma once #pragma once
#include "../constants/EntityIdentifiers.h" #include "../constants/EntityIdentifiers.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -18,7 +19,7 @@ class CConnection;
class ICPackVisitor; class ICPackVisitor;
struct DLL_LINKAGE CPack struct DLL_LINKAGE CPack : public Serializeable
{ {
/// Pointer to connection that pack received from /// Pointer to connection that pack received from
/// Only set & used on server /// Only set & used on server
+3 -3
View File
@@ -963,7 +963,7 @@ void FoWChange::applyGs(CGameState *gs)
TeamState * team = gs->getPlayerTeam(player); TeamState * team = gs->getPlayerTeam(player);
auto & fogOfWarMap = team->fogOfWarMap; auto & fogOfWarMap = team->fogOfWarMap;
for(const int3 & t : tiles) for(const int3 & t : tiles)
(*fogOfWarMap)[t.z][t.x][t.y] = mode != ETileVisibility::HIDDEN; fogOfWarMap[t.z][t.x][t.y] = mode != ETileVisibility::HIDDEN;
if (mode == ETileVisibility::HIDDEN) //do not hide too much if (mode == ETileVisibility::HIDDEN) //do not hide too much
{ {
@@ -986,7 +986,7 @@ void FoWChange::applyGs(CGameState *gs)
} }
} }
for(const int3 & t : tilesRevealed) //probably not the most optimal solution ever for(const int3 & t : tilesRevealed) //probably not the most optimal solution ever
(*fogOfWarMap)[t.z][t.x][t.y] = 1; fogOfWarMap[t.z][t.x][t.y] = 1;
} }
} }
@@ -1325,7 +1325,7 @@ void TryMoveHero::applyGs(CGameState *gs)
auto & fogOfWarMap = gs->getPlayerTeam(h->getOwner())->fogOfWarMap; auto & fogOfWarMap = gs->getPlayerTeam(h->getOwner())->fogOfWarMap;
for(const int3 & t : fowRevealed) for(const int3 & t : fowRevealed)
(*fogOfWarMap)[t.z][t.x][t.y] = 1; fogOfWarMap[t.z][t.x][t.y] = 1;
} }
void NewStructures::applyGs(CGameState *gs) void NewStructures::applyGs(CGameState *gs)
+2 -2
View File
@@ -19,13 +19,13 @@ VCMI_LIB_NAMESPACE_BEGIN
namespace PathfinderUtil namespace PathfinderUtil
{ {
using FoW = std::unique_ptr<boost::multi_array<ui8, 3>>; using FoW = boost::multi_array<ui8, 3>;
using ELayer = EPathfindingLayer; using ELayer = EPathfindingLayer;
template<EPathfindingLayer::Type layer> template<EPathfindingLayer::Type layer>
EPathAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile & tinfo, const FoW & fow, const PlayerColor player, const CGameState * gs) EPathAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile & tinfo, const FoW & fow, const PlayerColor player, const CGameState * gs)
{ {
if(!(*fow)[pos.z][pos.x][pos.y]) if(!fow[pos.z][pos.x][pos.y])
return EPathAccessibility::BLOCKED; return EPathAccessibility::BLOCKED;
switch(layer) switch(layer)
+2 -1
View File
@@ -12,6 +12,7 @@
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../ResourceSet.h" #include "../ResourceSet.h"
#include "../serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -26,7 +27,7 @@ using LimitersList = std::vector<std::shared_ptr<Rewardable::Limiter>>;
/// Limiters of rewards. Rewards will be granted to hero only if he satisfies requirements /// Limiters of rewards. Rewards will be granted to hero only if he satisfies requirements
/// Note: for this is only a test - it won't remove anything from hero (e.g. artifacts or creatures) /// Note: for this is only a test - it won't remove anything from hero (e.g. artifacts or creatures)
struct DLL_LINKAGE Limiter final struct DLL_LINKAGE Limiter final : public Serializeable
{ {
/// day of week, unused if 0, 1-7 will test for current day of week /// day of week, unused if 0, 1-7 will test for current day of week
si32 dayOfWeek; si32 dayOfWeek;
+2 -1
View File
@@ -11,6 +11,7 @@
#pragma once #pragma once
#include "../GameConstants.h" #include "../GameConstants.h"
#include "../serializer/Serializeable.h"
#include "CRmgTemplate.h" #include "CRmgTemplate.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -26,7 +27,7 @@ enum class EPlayerType
/// The map gen options class holds values about general map generation settings /// The map gen options class holds values about general map generation settings
/// e.g. the size of the map, the count of players,... /// e.g. the size of the map, the count of players,...
class DLL_LINKAGE CMapGenOptions class DLL_LINKAGE CMapGenOptions : public Serializeable
{ {
public: public:
/// The player settings class maps the player color, starting town and human player flag. /// The player settings class maps the player color, starting town and human player flag.
+138 -46
View File
@@ -35,7 +35,7 @@ public:
/// Main class for deserialization of classes from binary form /// Main class for deserialization of classes from binary form
/// Effectively revesed version of BinarySerializer /// Effectively revesed version of BinarySerializer
class DLL_LINKAGE BinaryDeserializer : public CLoaderBase class BinaryDeserializer : public CLoaderBase
{ {
template<typename Ser,typename T> template<typename Ser,typename T>
struct LoadIfStackInstance struct LoadIfStackInstance
@@ -101,9 +101,9 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
} }
}; };
STRONG_INLINE ui32 readAndCheckLength() STRONG_INLINE uint32_t readAndCheckLength()
{ {
ui32 length; uint32_t length;
load(length); load(length);
//NOTE: also used for h3m's embedded in campaigns, so it may be quite large in some cases (e.g. XXL maps with multiple objects) //NOTE: also used for h3m's embedded in campaigns, so it may be quite large in some cases (e.g. XXL maps with multiple objects)
if(length > 1000000) if(length > 1000000)
@@ -119,7 +119,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
class IPointerLoader class IPointerLoader
{ {
public: public:
virtual void * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER virtual Serializeable * loadPtr(CLoaderBase &ar, IGameCallback * cb, uint32_t pid) const =0; //data is pointer to the ACTUAL POINTER
virtual ~IPointerLoader() = default; virtual ~IPointerLoader() = default;
template<typename Type> static IPointerLoader *getApplier(const Type * t = nullptr) template<typename Type> static IPointerLoader *getApplier(const Type * t = nullptr)
@@ -132,7 +132,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
class CPointerLoader : public IPointerLoader class CPointerLoader : public IPointerLoader
{ {
public: public:
void * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const override //data is pointer to the ACTUAL POINTER Serializeable * loadPtr(CLoaderBase &ar, IGameCallback * cb, uint32_t pid) const override //data is pointer to the ACTUAL POINTER
{ {
auto & s = static_cast<BinaryDeserializer &>(ar); auto & s = static_cast<BinaryDeserializer &>(ar);
@@ -142,7 +142,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase
ptr->serialize(s); ptr->serialize(s);
return static_cast<void*>(ptr); return static_cast<Serializeable*>(ptr);
} }
}; };
@@ -156,13 +156,19 @@ public:
bool reverseEndianness; //if source has different endianness than us, we reverse bytes bool reverseEndianness; //if source has different endianness than us, we reverse bytes
Version version; Version version;
std::map<ui32, void*> loadedPointers; std::vector<std::string> loadedStrings;
std::map<const void*, std::shared_ptr<void>> loadedSharedPointers; std::map<uint32_t, Serializeable*> loadedPointers;
std::map<const Serializeable*, std::shared_ptr<Serializeable>> loadedSharedPointers;
IGameCallback * cb = nullptr; IGameCallback * cb = nullptr;
bool smartPointerSerialization; bool smartPointerSerialization;
bool saving; bool saving;
BinaryDeserializer(IBinaryReader * r); bool hasFeature(Version what) const
{
return version >= what;
};
DLL_LINKAGE BinaryDeserializer(IBinaryReader * r);
template<class T> template<class T>
BinaryDeserializer & operator&(T & t) BinaryDeserializer & operator&(T & t)
@@ -171,12 +177,56 @@ public:
return * this; return * this;
} }
template < class T, typename std::enable_if_t < std::is_fundamental_v<T> && !std::is_same_v<T, bool>, int > = 0 > int64_t loadEncodedInteger()
{
uint64_t valueUnsigned = 0;
uint_fast8_t offset = 0;
for (;;)
{
uint8_t byteValue;
load(byteValue);
if ((byteValue & 0x80) != 0)
{
valueUnsigned |= (byteValue & 0x7f) << offset;
offset += 7;
}
else
{
valueUnsigned |= (byteValue & 0x3f) << offset;
bool isNegative = (byteValue & 0x40) != 0;
if (isNegative)
return -static_cast<int64_t>(valueUnsigned);
else
return valueUnsigned;
}
}
}
template < class T, typename std::enable_if_t < std::is_floating_point_v<T>, int > = 0 >
void load(T &data) void load(T &data)
{ {
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness); this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
} }
template < class T, typename std::enable_if_t < std::is_integral_v<T> && !std::is_same_v<T, bool>, int > = 0 >
void load(T &data)
{
if constexpr (sizeof(T) == 1)
{
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
else
{
static_assert(!std::is_same_v<uint64_t, T>, "Serialization of unsigned 64-bit value may not work in some cases");
if (hasFeature(Version::COMPACT_INTEGER_SERIALIZATION))
data = loadEncodedInteger();
else
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
}
template < typename T, typename std::enable_if_t < is_serializeable<BinaryDeserializer, T>::value, int > = 0 > template < typename T, typename std::enable_if_t < is_serializeable<BinaryDeserializer, T>::value, int > = 0 >
void load(T &data) void load(T &data)
{ {
@@ -188,15 +238,20 @@ public:
template < typename T, typename std::enable_if_t < std::is_array_v<T>, int > = 0 > template < typename T, typename std::enable_if_t < std::is_array_v<T>, int > = 0 >
void load(T &data) void load(T &data)
{ {
ui32 size = std::size(data); uint32_t size = std::size(data);
for(ui32 i = 0; i < size; i++) for(uint32_t i = 0; i < size; i++)
load(data[i]); load(data[i]);
} }
void load(Version &data)
{
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
template < typename T, typename std::enable_if_t < std::is_enum_v<T>, int > = 0 > template < typename T, typename std::enable_if_t < std::is_enum_v<T>, int > = 0 >
void load(T &data) void load(T &data)
{ {
si32 read; int32_t read;
load( read ); load( read );
data = static_cast<T>(read); data = static_cast<T>(read);
} }
@@ -204,7 +259,7 @@ public:
template < typename T, typename std::enable_if_t < std::is_same_v<T, bool>, int > = 0 > template < typename T, typename std::enable_if_t < std::is_same_v<T, bool>, int > = 0 >
void load(T &data) void load(T &data)
{ {
ui8 read; uint8_t read;
load( read ); load( read );
data = static_cast<bool>(read); data = static_cast<bool>(read);
} }
@@ -212,18 +267,18 @@ public:
template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0> template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0>
void load(std::vector<T> &data) void load(std::vector<T> &data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
data.resize(length); data.resize(length);
for(ui32 i=0;i<length;i++) for(uint32_t i=0;i<length;i++)
load( data[i]); load( data[i]);
} }
template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0> template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0>
void load(std::deque<T> & data) void load(std::deque<T> & data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
data.resize(length); data.resize(length);
for(ui32 i = 0; i < length; i++) for(uint32_t i = 0; i < length; i++)
load(data[i]); load(data[i]);
} }
@@ -281,7 +336,7 @@ public:
return; return;
} }
ui32 pid = 0xffffffff; //pointer id (or maybe rather pointee id) uint32_t pid = 0xffffffff; //pointer id (or maybe rather pointee id)
if(smartPointerSerialization) if(smartPointerSerialization)
{ {
load( pid ); //get the id load( pid ); //get the id
@@ -291,12 +346,12 @@ public:
{ {
// We already got this pointer // We already got this pointer
// Cast it in case we are loading it to a non-first base pointer // Cast it in case we are loading it to a non-first base pointer
data = static_cast<T>(i->second); data = dynamic_cast<T>(i->second);
return; return;
} }
} }
//get type id //get type id
ui16 tid; uint16_t tid;
load( tid ); load( tid );
if(!tid) if(!tid)
@@ -316,15 +371,15 @@ public:
data = nullptr; data = nullptr;
return; return;
} }
data = static_cast<T>(app->loadPtr(*this, cb, pid)); data = dynamic_cast<T>(app->loadPtr(*this, cb, pid));
} }
} }
template <typename T> template <typename T>
void ptrAllocated(const T *ptr, ui32 pid) void ptrAllocated(T *ptr, uint32_t pid)
{ {
if(smartPointerSerialization && pid != 0xffffffff) if(smartPointerSerialization && pid != 0xffffffff)
loadedPointers[pid] = (void*)ptr; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt loadedPointers[pid] = const_cast<Serializeable*>(dynamic_cast<const Serializeable*>(ptr)); //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
} }
template<typename Base, typename Derived> void registerType(const Base * b = nullptr, const Derived * d = nullptr) template<typename Base, typename Derived> void registerType(const Base * b = nullptr, const Derived * d = nullptr)
@@ -339,7 +394,7 @@ public:
NonConstT *internalPtr; NonConstT *internalPtr;
load(internalPtr); load(internalPtr);
void * internalPtrDerived = static_cast<void*>(internalPtr); const auto * internalPtrDerived = static_cast<Serializeable*>(internalPtr);
if(internalPtr) if(internalPtr)
{ {
@@ -354,7 +409,7 @@ public:
{ {
auto hlp = std::shared_ptr<NonConstT>(internalPtr); auto hlp = std::shared_ptr<NonConstT>(internalPtr);
data = hlp; data = hlp;
loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<void>(hlp); loadedSharedPointers[internalPtrDerived] = std::static_pointer_cast<Serializeable>(hlp);
} }
} }
else else
@@ -386,16 +441,16 @@ public:
template <typename T, size_t N> template <typename T, size_t N>
void load(std::array<T, N> &data) void load(std::array<T, N> &data)
{ {
for(ui32 i = 0; i < N; i++) for(uint32_t i = 0; i < N; i++)
load( data[i] ); load( data[i] );
} }
template <typename T> template <typename T>
void load(std::set<T> &data) void load(std::set<T> &data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
data.clear(); data.clear();
T ins; T ins;
for(ui32 i=0;i<length;i++) for(uint32_t i=0;i<length;i++)
{ {
load( ins ); load( ins );
data.insert(ins); data.insert(ins);
@@ -404,10 +459,10 @@ public:
template <typename T, typename U> template <typename T, typename U>
void load(std::unordered_set<T, U> &data) void load(std::unordered_set<T, U> &data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
data.clear(); data.clear();
T ins; T ins;
for(ui32 i=0;i<length;i++) for(uint32_t i=0;i<length;i++)
{ {
load(ins); load(ins);
data.insert(ins); data.insert(ins);
@@ -416,10 +471,10 @@ public:
template <typename T> template <typename T>
void load(std::list<T> &data) void load(std::list<T> &data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
data.clear(); data.clear();
T ins; T ins;
for(ui32 i=0;i<length;i++) for(uint32_t i=0;i<length;i++)
{ {
load(ins); load(ins);
data.push_back(ins); data.push_back(ins);
@@ -433,12 +488,25 @@ public:
} }
template <typename T1, typename T2> template <typename T1, typename T2>
void load(std::map<T1,T2> &data) void load(std::unordered_map<T1,T2> &data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
data.clear(); data.clear();
T1 key; T1 key;
for(ui32 i=0;i<length;i++) for(uint32_t i=0;i<length;i++)
{
load(key);
load(data[key]);
}
}
template <typename T1, typename T2>
void load(std::map<T1,T2> &data)
{
uint32_t length = readAndCheckLength();
data.clear();
T1 key;
for(uint32_t i=0;i<length;i++)
{ {
load(key); load(key);
load(data[key]); load(data[key]);
@@ -446,15 +514,39 @@ public:
} }
void load(std::string &data) void load(std::string &data)
{ {
ui32 length = readAndCheckLength(); if (hasFeature(Version::COMPACT_STRING_SERIALIZATION))
data.resize(length); {
this->read(static_cast<void *>(data.data()), length, false); int32_t length;
load(length);
if (length < 0)
{
int32_t stringID = -length - 1; // -1, -2 ... -> 0, 1 ...
data = loadedStrings[stringID];
}
if (length == 0)
{
data = {};
}
if (length > 0)
{
data.resize(length);
this->read(static_cast<void *>(data.data()), length, false);
loadedStrings.push_back(data);
}
}
else
{
uint32_t length = readAndCheckLength();
data.resize(length);
this->read(static_cast<void *>(data.data()), length, false);
}
} }
template<typename... TN> template<typename... TN>
void load(std::variant<TN...> & data) void load(std::variant<TN...> & data)
{ {
si32 which; int32_t which;
load( which ); load( which );
assert(which < sizeof...(TN)); assert(which < sizeof...(TN));
@@ -469,7 +561,7 @@ public:
template<typename T> template<typename T>
void load(std::optional<T> & data) void load(std::optional<T> & data)
{ {
ui8 present; uint8_t present;
load( present ); load( present );
if(present) if(present)
{ {
@@ -487,16 +579,16 @@ public:
template <typename T> template <typename T>
void load(boost::multi_array<T, 3> & data) void load(boost::multi_array<T, 3> & data)
{ {
ui32 length = readAndCheckLength(); uint32_t length = readAndCheckLength();
ui32 x; uint32_t x;
ui32 y; uint32_t y;
ui32 z; uint32_t z;
load(x); load(x);
load(y); load(y);
load(z); load(z);
data.resize(boost::extents[x][y][z]); data.resize(boost::extents[x][y][z]);
assert(length == data.num_elements()); //x*y*z should be equal to number of elements assert(length == data.num_elements()); //x*y*z should be equal to number of elements
for(ui32 i = 0; i < length; i++) for(uint32_t i = 0; i < length; i++)
load(data.data()[i]); load(data.data()[i]);
} }
template <std::size_t T> template <std::size_t T>
+120 -32
View File
@@ -12,6 +12,7 @@
#include "CSerializer.h" #include "CSerializer.h"
#include "CTypeList.h" #include "CTypeList.h"
#include "ESerializationVersion.h" #include "ESerializationVersion.h"
#include "Serializeable.h"
#include "../mapObjects/CArmedInstance.h" #include "../mapObjects/CArmedInstance.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@@ -23,7 +24,7 @@ protected:
public: public:
CSaverBase(IBinaryWriter * w): writer(w){}; CSaverBase(IBinaryWriter * w): writer(w){};
inline void write(const void * data, unsigned size) void write(const void * data, unsigned size)
{ {
writer->write(reinterpret_cast<const std::byte*>(data), size); writer->write(reinterpret_cast<const std::byte*>(data), size);
}; };
@@ -34,7 +35,7 @@ public:
/// Primitives: copy memory into underlying stream (defined in CSaverBase) /// Primitives: copy memory into underlying stream (defined in CSaverBase)
/// Containers: custom overloaded method that decouples class into primitives /// Containers: custom overloaded method that decouples class into primitives
/// VCMI Classes: recursively serialize them via ClassName::serialize( BinarySerializer &, int version) call /// VCMI Classes: recursively serialize them via ClassName::serialize( BinarySerializer &, int version) call
class DLL_LINKAGE BinarySerializer : public CSaverBase class BinarySerializer : public CSaverBase
{ {
template<typename Handler> template<typename Handler>
struct VariantVisitorSaver struct VariantVisitorSaver
@@ -85,7 +86,7 @@ class DLL_LINKAGE BinarySerializer : public CSaverBase
{ {
public: public:
virtual void savePtr(CSaverBase &ar, const void *data) const =0; virtual void savePtr(CSaverBase &ar, const void *data) const =0;
virtual ~CBasicPointerSaver(){} virtual ~CBasicPointerSaver() = default;
template<typename T> static CBasicPointerSaver *getApplier(const T * t=nullptr) template<typename T> static CBasicPointerSaver *getApplier(const T * t=nullptr)
{ {
@@ -113,13 +114,19 @@ class DLL_LINKAGE BinarySerializer : public CSaverBase
public: public:
using Version = ESerializationVersion; using Version = ESerializationVersion;
std::map<const void*, ui32> savedPointers; std::map<std::string, uint32_t> savedStrings;
std::map<const Serializeable*, uint32_t> savedPointers;
const Version version = Version::CURRENT; const Version version = Version::CURRENT;
bool smartPointerSerialization; bool smartPointerSerialization;
bool saving; bool saving;
BinarySerializer(IBinaryWriter * w); bool hasFeature(Version what) const
{
return version >= what;
};
DLL_LINKAGE BinarySerializer(IBinaryWriter * w);
template<typename Base, typename Derived> template<typename Base, typename Derived>
void registerType(const Base * b = nullptr, const Derived * d = nullptr) void registerType(const Base * b = nullptr, const Derived * d = nullptr)
@@ -134,32 +141,72 @@ public:
return * this; return * this;
} }
void saveEncodedInteger(int64_t value)
{
uint64_t valueUnsigned = std::abs(value);
while (valueUnsigned > 0x3f)
{
uint8_t byteValue = (valueUnsigned & 0x7f) | 0x80;
valueUnsigned = valueUnsigned >> 7;
save(byteValue);
}
uint8_t lastByteValue = valueUnsigned & 0x3f;
if (value < 0)
lastByteValue |= 0x40;
save(lastByteValue);
}
template < typename T, typename std::enable_if_t < std::is_same_v<T, bool>, int > = 0 > template < typename T, typename std::enable_if_t < std::is_same_v<T, bool>, int > = 0 >
void save(const T &data) void save(const T &data)
{ {
ui8 writ = static_cast<ui8>(data); uint8_t writ = static_cast<uint8_t>(data);
save(writ); save(writ);
} }
template < class T, typename std::enable_if_t < std::is_fundamental_v<T> && !std::is_same_v<T, bool>, int > = 0 > template < class T, typename std::enable_if_t < std::is_floating_point_v<T>, int > = 0 >
void save(const T &data) void save(const T &data)
{ {
// save primitive - simply dump binary data to output // save primitive - simply dump binary data to output
this->write(static_cast<const void *>(&data), sizeof(data)); this->write(static_cast<const void *>(&data), sizeof(data));
} }
template < class T, typename std::enable_if_t < std::is_integral_v<T> && !std::is_same_v<T, bool>, int > = 0 >
void save(const T &data)
{
if constexpr (sizeof(T) == 1)
{
// save primitive - simply dump binary data to output
this->write(static_cast<const void *>(&data), sizeof(data));
}
else
{
if (hasFeature(Version::COMPACT_INTEGER_SERIALIZATION))
saveEncodedInteger(data);
else
this->write(static_cast<const void *>(&data), sizeof(data));
}
}
void save(const Version &data)
{
this->write(static_cast<const void *>(&data), sizeof(data));
}
template < typename T, typename std::enable_if_t < std::is_enum_v<T>, int > = 0 > template < typename T, typename std::enable_if_t < std::is_enum_v<T>, int > = 0 >
void save(const T &data) void save(const T &data)
{ {
si32 writ = static_cast<si32>(data); int32_t writ = static_cast<int32_t>(data);
*this & writ; *this & writ;
} }
template < typename T, typename std::enable_if_t < std::is_array_v<T>, int > = 0 > template < typename T, typename std::enable_if_t < std::is_array_v<T>, int > = 0 >
void save(const T &data) void save(const T &data)
{ {
ui32 size = std::size(data); uint32_t size = std::size(data);
for(ui32 i=0; i < size; i++) for(uint32_t i=0; i < size; i++)
*this & data[i]; *this & data[i];
} }
@@ -214,7 +261,7 @@ public:
{ {
// We might have an object that has multiple inheritance and store it via the non-first base pointer. // We might have an object that has multiple inheritance and store it via the non-first base pointer.
// Therefore, all pointers need to be normalized to the actual object address. // Therefore, all pointers need to be normalized to the actual object address.
const void * actualPointer = static_cast<const void*>(data); const auto * actualPointer = static_cast<const Serializeable*>(data);
auto i = savedPointers.find(actualPointer); auto i = savedPointers.find(actualPointer);
if(i != savedPointers.end()) if(i != savedPointers.end())
{ {
@@ -224,7 +271,7 @@ public:
} }
//give id to this pointer //give id to this pointer
ui32 pid = (ui32)savedPointers.size(); uint32_t pid = savedPointers.size();
savedPointers[actualPointer] = pid; savedPointers[actualPointer] = pid;
save(pid); save(pid);
} }
@@ -271,30 +318,30 @@ public:
template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0> template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0>
void save(const std::vector<T> &data) void save(const std::vector<T> &data)
{ {
ui32 length = (ui32)data.size(); uint32_t length = data.size();
*this & length; *this & length;
for(ui32 i=0;i<length;i++) for(uint32_t i=0;i<length;i++)
save(data[i]); save(data[i]);
} }
template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0> template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0>
void save(const std::deque<T> & data) void save(const std::deque<T> & data)
{ {
ui32 length = (ui32)data.size(); uint32_t length = data.size();
*this & length; *this & length;
for(ui32 i = 0; i < length; i++) for(uint32_t i = 0; i < length; i++)
save(data[i]); save(data[i]);
} }
template <typename T, size_t N> template <typename T, size_t N>
void save(const std::array<T, N> &data) void save(const std::array<T, N> &data)
{ {
for(ui32 i=0; i < N; i++) for(uint32_t i=0; i < N; i++)
save(data[i]); save(data[i]);
} }
template <typename T> template <typename T>
void save(const std::set<T> &data) void save(const std::set<T> &data)
{ {
auto & d = const_cast<std::set<T> &>(data); auto & d = const_cast<std::set<T> &>(data);
ui32 length = (ui32)d.size(); uint32_t length = d.size();
save(length); save(length);
for(auto i = d.begin(); i != d.end(); i++) for(auto i = d.begin(); i != d.end(); i++)
save(*i); save(*i);
@@ -303,7 +350,7 @@ public:
void save(const std::unordered_set<T, U> &data) void save(const std::unordered_set<T, U> &data)
{ {
auto & d = const_cast<std::unordered_set<T, U> &>(data); auto & d = const_cast<std::unordered_set<T, U> &>(data);
ui32 length = (ui32)d.size(); uint32_t length = d.size();
*this & length; *this & length;
for(auto i = d.begin(); i != d.end(); i++) for(auto i = d.begin(); i != d.end(); i++)
save(*i); save(*i);
@@ -312,16 +359,47 @@ public:
void save(const std::list<T> &data) void save(const std::list<T> &data)
{ {
auto & d = const_cast<std::list<T> &>(data); auto & d = const_cast<std::list<T> &>(data);
ui32 length = (ui32)d.size(); uint32_t length = d.size();
*this & length; *this & length;
for(auto i = d.begin(); i != d.end(); i++) for(auto i = d.begin(); i != d.end(); i++)
save(*i); save(*i);
} }
void save(const std::string &data) void save(const std::string &data)
{ {
save(ui32(data.length())); if (hasFeature(Version::COMPACT_STRING_SERIALIZATION))
this->write(static_cast<const void *>(data.data()), data.size()); {
if (data.empty())
{
save(static_cast<uint32_t>(0));
return;
}
auto it = savedStrings.find(data);
if (it == savedStrings.end())
{
save(static_cast<uint32_t>(data.length()));
this->write(static_cast<const void *>(data.data()), data.size());
// -1, -2...
int32_t newStringID = -1 - savedStrings.size();
savedStrings[data] = newStringID;
}
else
{
int32_t index = it->second;
save(index);
}
}
else
{
save(static_cast<uint32_t>(data.length()));
this->write(static_cast<const void *>(data.data()), data.size());
}
} }
template <typename T1, typename T2> template <typename T1, typename T2>
void save(const std::pair<T1,T2> &data) void save(const std::pair<T1,T2> &data)
{ {
@@ -329,9 +407,19 @@ public:
save(data.second); save(data.second);
} }
template <typename T1, typename T2> template <typename T1, typename T2>
void save(const std::unordered_map<T1,T2> &data)
{
*this & static_cast<uint32_t>(data.size());
for(auto i = data.begin(); i != data.end(); i++)
{
save(i->first);
save(i->second);
}
}
template <typename T1, typename T2>
void save(const std::map<T1,T2> &data) void save(const std::map<T1,T2> &data)
{ {
*this & ui32(data.size()); *this & static_cast<uint32_t>(data.size());
for(auto i = data.begin(); i != data.end(); i++) for(auto i = data.begin(); i != data.end(); i++)
{ {
save(i->first); save(i->first);
@@ -341,7 +429,7 @@ public:
template <typename T1, typename T2> template <typename T1, typename T2>
void save(const std::multimap<T1, T2> &data) void save(const std::multimap<T1, T2> &data)
{ {
*this & ui32(data.size()); *this & static_cast<uint32_t>(data.size());
for(auto i = data.begin(); i != data.end(); i++) for(auto i = data.begin(); i != data.end(); i++)
{ {
save(i->first); save(i->first);
@@ -351,7 +439,7 @@ public:
template<typename T0, typename... TN> template<typename T0, typename... TN>
void save(const std::variant<T0, TN...> & data) void save(const std::variant<T0, TN...> & data)
{ {
si32 which = data.index(); int32_t which = data.index();
save(which); save(which);
VariantVisitorSaver<BinarySerializer> visitor(*this); VariantVisitorSaver<BinarySerializer> visitor(*this);
@@ -362,26 +450,26 @@ public:
{ {
if(data) if(data)
{ {
save((ui8)1); save(static_cast<uint8_t>(1));
save(*data); save(*data);
} }
else else
{ {
save((ui8)0); save(static_cast<uint32_t>(0));
} }
} }
template <typename T> template <typename T>
void save(const boost::multi_array<T, 3> &data) void save(const boost::multi_array<T, 3> &data)
{ {
ui32 length = data.num_elements(); uint32_t length = data.num_elements();
*this & length; *this & length;
auto shape = data.shape(); auto shape = data.shape();
ui32 x = shape[0]; uint32_t x = shape[0];
ui32 y = shape[1]; uint32_t y = shape[1];
ui32 z = shape[2]; uint32_t z = shape[2];
*this & x & y & z; *this & x & y & z;
for(ui32 i = 0; i < length; i++) for(uint32_t i = 0; i < length; i++)
save(data.data()[i]); save(data.data()[i]);
} }
template <std::size_t T> template <std::size_t T>
-6
View File
@@ -25,14 +25,8 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
{ {
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects, registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
[](const CGObjectInstance &obj){ return obj.id; }); [](const CGObjectInstance &obj){ return obj.id; });
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->objects,
[](const CHero &h){ return h.getId(); });
registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes, registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
[](const CGHeroInstance &h){ return h.type->getId(); }); [](const CGHeroInstance &h){ return h.type->getId(); });
registerVectoredType<CCreature, CreatureID>(&lib->creh->objects,
[](const CCreature &cre){ return cre.getId(); });
registerVectoredType<CArtifact, ArtifactID>(&lib->arth->objects,
[](const CArtifact &art){ return art.getId(); });
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances, registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
[](const CArtifactInstance &artInst){ return artInst.getId(); }); [](const CArtifactInstance &artInst){ return artInst.getId(); });
registerVectoredType<CQuest, si32>(&gs->map->quests, registerVectoredType<CQuest, si32>(&gs->map->quests,
+6 -1
View File
@@ -44,5 +44,10 @@ enum class ESerializationVersion : int32_t
RELEASE_150 = ARTIFACT_COSTUMES, // for convenience RELEASE_150 = ARTIFACT_COSTUMES, // for convenience
CURRENT = ARTIFACT_COSTUMES COMPACT_STRING_SERIALIZATION, // 841 - optimized serialization of previoulsy encountered strings
COMPACT_INTEGER_SERIALIZATION, // 842 - serialize integers in forms similar to protobuf
REMOVE_FOG_OF_WAR_POINTER, // 843 - fog of war is serialized as reference instead of pointer
SIMPLE_TEXT_CONTAINER_SERIALIZATION, // 844 - text container is serialized using common routine instead of custom approach
CURRENT = SIMPLE_TEXT_CONTAINER_SERIALIZATION
}; };
+21
View File
@@ -0,0 +1,21 @@
/*
* Serializeable.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
VCMI_LIB_NAMESPACE_BEGIN
// Tag class that acts as base for all classes that can be serialized by pointer
class Serializeable
{
public:
virtual ~Serializeable() = default;
};
VCMI_LIB_NAMESPACE_END
+1 -1
View File
@@ -735,7 +735,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
{ {
ObjectPosInfo posInfo(obj); ObjectPosInfo posInfo(obj);
if((*fowMap)[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0) if(fowMap[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0)
pack.objectPositions.push_back(posInfo); pack.objectPositions.push_back(posInfo);
} }
} }
+2 -2
View File
@@ -884,11 +884,11 @@ void CGameHandler::onNewTurn()
// find all hidden tiles // find all hidden tiles
const auto & fow = getPlayerTeam(player)->fogOfWarMap; const auto & fow = getPlayerTeam(player)->fogOfWarMap;
auto shape = fow->shape(); auto shape = fow.shape();
for(size_t z = 0; z < shape[0]; z++) for(size_t z = 0; z < shape[0]; z++)
for(size_t x = 0; x < shape[1]; x++) for(size_t x = 0; x < shape[1]; x++)
for(size_t y = 0; y < shape[2]; y++) for(size_t y = 0; y < shape[2]; y++)
if (!(*fow)[z][x][y]) if (!fow[z][x][y])
fw.tiles.insert(int3(x, y, z)); fw.tiles.insert(int3(x, y, z));
sendAndApply (&fw); sendAndApply (&fw);
+1 -1
View File
@@ -367,7 +367,7 @@ void PlayerMessageProcessor::cheatMapReveal(PlayerColor player, bool reveal)
for(int z = 0; z < mapSize.z; z++) for(int z = 0; z < mapSize.z; z++)
for(int x = 0; x < mapSize.x; x++) for(int x = 0; x < mapSize.x; x++)
for(int y = 0; y < mapSize.y; y++) for(int y = 0; y < mapSize.y; y++)
if(!(*fowMap)[z][x][y] || fc.mode == ETileVisibility::HIDDEN) if(!fowMap[z][x][y] || fc.mode == ETileVisibility::HIDDEN)
hlp_tab[lastUnc++] = int3(x, y, z); hlp_tab[lastUnc++] = int3(x, y, z);
fc.tiles.insert(hlp_tab, hlp_tab + lastUnc); fc.tiles.insert(hlp_tab, hlp_tab + lastUnc);