1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Use JsonSerializeFormat for map objects

This commit is contained in:
AlexVinS
2016-02-22 02:37:19 +03:00
parent 15a4a11560
commit dd1aabbe23
19 changed files with 344 additions and 366 deletions

View File

@@ -11,6 +11,7 @@
#include "spells/CSpellHandler.h" #include "spells/CSpellHandler.h"
#include "CHeroHandler.h" #include "CHeroHandler.h"
#include "IBonusTypeHandler.h" #include "IBonusTypeHandler.h"
#include "serializer/JsonSerializeFormat.h"
/* /*
* CCreatureSet.cpp, part of VCMI engine * CCreatureSet.cpp, part of VCMI engine
@@ -479,9 +480,16 @@ CCreatureSet & CCreatureSet::operator=(const CCreatureSet&cs)
void CCreatureSet::armyChanged() void CCreatureSet::armyChanged()
{ {
} }
void CCreatureSet::writeJson(JsonNode& json) const void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName)
{
if(handler.saving && stacks.empty())
return;
JsonNode & json = handler.getCurrent()[fieldName];
if(handler.saving)
{ {
for(const auto & p : stacks) for(const auto & p : stacks)
{ {
@@ -490,8 +498,7 @@ void CCreatureSet::writeJson(JsonNode& json) const
json.Vector()[p.first.getNum()] = stack_node; json.Vector()[p.first.getNum()] = stack_node;
} }
} }
else
void CCreatureSet::readJson(const JsonNode& json)
{ {
for(size_t idx = 0; idx < json.Vector().size(); idx++) for(size_t idx = 0; idx < json.Vector().size(); idx++)
{ {
@@ -502,6 +509,7 @@ void CCreatureSet::readJson(const JsonNode& json)
putStack(SlotID(idx), new_stack); putStack(SlotID(idx), new_stack);
} }
} }
}
CStackInstance::CStackInstance() CStackInstance::CStackInstance()
: armyObj(_armyObj) : armyObj(_armyObj)

View File

@@ -19,6 +19,7 @@ class CCreature;
class CGHeroInstance; class CGHeroInstance;
class CArmedInstance; class CArmedInstance;
class CCreatureArtifactSet; class CCreatureArtifactSet;
class JsonSerializeFormat;
class DLL_LINKAGE CStackBasicDescriptor class DLL_LINKAGE CStackBasicDescriptor
{ {
@@ -220,10 +221,7 @@ public:
h & stacks & formation; h & stacks & formation;
} }
void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName);
void writeJson(JsonNode & json) const;
void readJson(const JsonNode & json);
operator bool() const operator bool() const
{ {

View File

@@ -132,13 +132,3 @@ CBonusSystemNode * CArmedInstance::whatShouldBeAttached()
{ {
return this; return this;
} }
void CArmedInstance::writeJsonOptions(JsonNode& json) const
{
CGObjectInstance::writeJsonOptions(json);
}
void CArmedInstance::readJsonOptions(const JsonNode& json)
{
CGObjectInstance::readJsonOptions(json);
}

View File

@@ -40,7 +40,4 @@ public:
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CCreatureSet&>(*this); h & static_cast<CCreatureSet&>(*this);
} }
protected:
void writeJsonOptions(JsonNode & json) const override;
void readJsonOptions(const JsonNode & json) override;
}; };

View File

@@ -25,6 +25,7 @@
#include "../CTownHandler.h" #include "../CTownHandler.h"
#include "../mapping/CMap.h" #include "../mapping/CMap.h"
#include "CGTownInstance.h" #include "CGTownInstance.h"
#include "../serializer/JsonSerializeFormat.h"
///helpers ///helpers
static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const ui16 soundID) static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const ui16 soundID)
@@ -1470,29 +1471,28 @@ bool CGHeroInstance::hasVisions(const CGObjectInstance * target, const int subty
return (distance < visionsRange) && (target->pos.z == pos.z); return (distance < visionsRange) && (target->pos.z == pos.z);
} }
void CGHeroInstance::writeJsonOptions(JsonNode& json) const void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat& handler)
{
serializeJsonOwner(handler);
if(handler.saving)
{ {
if(type) if(type)
{ {
json["type"].String() = type->identifier; handler.serializeString("type", type->identifier);
} }
else else
{ {
json["type"].String() = VLC->heroh->heroes[subID]->identifier; auto temp = VLC->heroh->heroes[subID]->identifier;
handler.serializeString("type", temp);
} }
CGObjectInstance::writeOwner(json);
CCreatureSet::writeJson(json["army"]);
CArtifactSet::writeJson(json["artifacts"]);
} }
else
void CGHeroInstance::readJsonOptions(const JsonNode& json)
{ {
if(ID == Obj::HERO || ID == Obj::PRISON) if(ID == Obj::HERO || ID == Obj::PRISON)
{ {
auto typeName = json["type"].String(); std::string typeName;
handler.serializeString("type", typeName);
auto rawId = VLC->modh->identifiers.getIdentifier("core", "hero", typeName); auto rawId = VLC->modh->identifiers.getIdentifier("core", "hero", typeName);
@@ -1501,11 +1501,17 @@ void CGHeroInstance::readJsonOptions(const JsonNode& json)
else else
subID = 0; //fallback to Orrin, throw error instead? subID = 0; //fallback to Orrin, throw error instead?
} }
}
CCreatureSet::serializeJson(handler, "army");
CGObjectInstance::readOwner(json); {
auto artifacts = handler.enterStruct("artifacts");
if(handler.saving)
CArtifactSet::writeJson(handler.getCurrent());
else
CArtifactSet::readJson(handler.getCurrent());
}
CCreatureSet::readJson(json["army"]);
CArtifactSet::readJson(json["artifacts"]);
} }
bool CGHeroInstance::isMissionCritical() const bool CGHeroInstance::isMissionCritical() const

View File

@@ -251,8 +251,7 @@ public:
std::string getObjectName() const override; std::string getObjectName() const override;
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override;//synchr void setPropertyDer(ui8 what, ui32 val) override;//synchr
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
private: private:
void levelUpAutomatically(); void levelUpAutomatically();

View File

@@ -19,6 +19,7 @@
#include "../CGameState.h" #include "../CGameState.h"
#include "../mapping/CMapDefines.h" #include "../mapping/CMapDefines.h"
#include "../CPlayerState.h" #include "../CPlayerState.h"
#include "../serializer/JsonSerializeFormat.h"
std::vector<const CArtifact *> CGTownInstance::merchantArtifacts; std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
std::vector<int> CGTownInstance::universitySkills; std::vector<int> CGTownInstance::universitySkills;
@@ -314,18 +315,11 @@ void CGDwelling::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
} }
} }
void CGDwelling::writeJsonOptions(JsonNode& json) const void CGDwelling::serializeJsonOptions(JsonSerializeFormat & handler)
{ {
//todo:CGDwelling::writeJsonOptions //todo: CGDwelling::serializeJsonOptions
if(ID != Obj::WAR_MACHINE_FACTORY && ID != Obj::REFUGEE_CAMP) if(ID != Obj::WAR_MACHINE_FACTORY && ID != Obj::REFUGEE_CAMP)
CGObjectInstance::writeOwner(json); serializeJsonOwner(handler);
}
void CGDwelling::readJsonOptions(const JsonNode& json)
{
//todo:CGDwelling::readJsonOptions
if(ID != Obj::WAR_MACHINE_FACTORY && ID != Obj::REFUGEE_CAMP)
CGObjectInstance::readOwner(json);
} }
int CGTownInstance::getSightRadius() const //returns sight distance int CGTownInstance::getSightRadius() const //returns sight distance
@@ -1129,6 +1123,14 @@ void CGTownInstance::battleFinished(const CGHeroInstance *hero, const BattleResu
} }
} }
void CGTownInstance::serializeJsonOptions(JsonSerializeFormat& handler)
{
CGObjectInstance::serializeJsonOwner(handler);
CCreatureSet::serializeJson(handler, "army");
//todo: CGTownInstance::serializeJsonOptions
}
COPWBonus::COPWBonus (BuildingID index, CGTownInstance *TOWN) COPWBonus::COPWBonus (BuildingID index, CGTownInstance *TOWN)
{ {
ID = index; ID = index;

View File

@@ -53,8 +53,7 @@ public:
TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount> TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
private: private:
void initObj() override; void initObj() override;
@@ -256,4 +255,5 @@ public:
std::string getObjectName() const override; std::string getObjectName() const override;
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ui8 what, ui32 val) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override;
}; };

View File

@@ -24,6 +24,8 @@
#include "CObjectClassesHandler.h" #include "CObjectClassesHandler.h"
#include "CGTownInstance.h" #include "CGTownInstance.h"
#include "../serializer/JsonSerializeFormat.h"
IGameCallback * IObjectInterface::cb = nullptr; IGameCallback * IObjectInterface::cb = nullptr;
///helpers ///helpers
@@ -331,64 +333,70 @@ bool CGObjectInstance::passableFor(PlayerColor color) const
return false; return false;
} }
void CGObjectInstance::writeJson(JsonNode & json) const void CGObjectInstance::serializeJson(JsonSerializeFormat & handler)
{ {
logGlobal->debugStream() <<"Save: [" << pos << "] " << id << " " << ID << " " << subID << " " << typeName << " " << subTypeName; if(handler.saving)
{
json.setType(JsonNode::DATA_STRUCT); handler.serializeString("type", typeName);
json["type"].String() = typeName; handler.serializeString("subType", subTypeName);
json["subType"].String() = subTypeName;
json["x"].Float() = pos.x;
json["y"].Float() = pos.y;
json["l"].Float() = pos.z;
appearance.writeJson(json["template"], false);
writeJsonOptions(json["options"]);
} }
void CGObjectInstance::readJson(const JsonNode & json) handler.serializeNumeric("x", pos.x);
handler.serializeNumeric("y", pos.y);
handler.serializeNumeric("l", pos.z);
if(handler.saving)
{ {
if(json.getType() != JsonNode::DATA_STRUCT) appearance.writeJson(handler.getCurrent()["template"], false);
{
logGlobal->error("Invalid object instance data");
return;
} }
pos.x = json["x"].Float(); else
pos.y = json["y"].Float(); {
pos.z = json["l"].Float(); appearance.readJson(handler.getCurrent()["template"], false);
appearance.readJson(json["template"], false);
readJsonOptions(json["options"]);
} }
void CGObjectInstance::writeJsonOptions(JsonNode & json) const
{ {
json.setType(JsonNode::DATA_STRUCT); auto options = handler.enterStruct("options");
serializeJsonOptions(handler);
} }
void CGObjectInstance::readJsonOptions(const JsonNode & json) if(handler.saving && handler.getCurrent()["options"].isNull())
{ {
handler.getCurrent().Struct().erase("options");
}
} }
void CGObjectInstance::writeOwner(JsonNode & json) const void CGObjectInstance::serializeJsonOptions(JsonSerializeFormat & handler)
{
}
void CGObjectInstance::serializeJsonOwner(JsonSerializeFormat & handler)
{
std::string temp;
//todo: use enum serialize
if(handler.saving)
{ {
if(tempOwner.isValidPlayer()) if(tempOwner.isValidPlayer())
{ {
json["owner"].String() = GameConstants::PLAYER_COLOR_NAMES[tempOwner.getNum()]; temp = GameConstants::PLAYER_COLOR_NAMES[tempOwner.getNum()];
handler.serializeString("owner", temp);
} }
} }
else
void CGObjectInstance::readOwner(const JsonNode & json)
{ {
tempOwner = PlayerColor::NEUTRAL;//this method assumes that object is ownable tempOwner = PlayerColor::NEUTRAL;//this method assumes that object is ownable
if(json["owner"].getType() == JsonNode::DATA_STRING)
handler.serializeString("owner", temp);
if(temp != "")
{ {
auto rawOwner = vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, json["owner"].String()); auto rawOwner = vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, temp);
if(rawOwner >=0) if(rawOwner >=0)
tempOwner = PlayerColor(rawOwner); tempOwner = PlayerColor(rawOwner);
else else
logGlobal->errorStream() << "Invalid owner :" << json["owner"].String(); logGlobal->errorStream() << "Invalid owner :" << temp;
}
} }
} }

View File

@@ -21,6 +21,7 @@ class IGameCallback;
class CGObjectInstance; class CGObjectInstance;
struct MetaString; struct MetaString;
struct BattleResult; struct BattleResult;
class JsonSerializeFormat;
// This one teleport-specific, but has to be available everywhere in callbacks and netpacks // This one teleport-specific, but has to be available everywhere in callbacks and netpacks
// For now it's will be there till teleports code refactored and moved into own file // For now it's will be there till teleports code refactored and moved into own file
@@ -186,10 +187,7 @@ public:
} }
///Entry point of Json serialization ///Entry point of Json serialization
void writeJson(JsonNode & json) const; void serializeJson(JsonSerializeFormat & handler);
///Entry point of Json de-serialization
void readJson(const JsonNode & json);
protected: protected:
/// virtual method that allows synchronously update object state on server and all clients /// virtual method that allows synchronously update object state on server and all clients
@@ -198,16 +196,11 @@ protected:
/// Gives dummy bonus from this object to hero. Can be used to track visited state /// Gives dummy bonus from this object to hero. Can be used to track visited state
void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const; void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const;
///Saves object-type specific options ///Serialize object-type specific options
///(!) do not forget to call inherited method first when overriding virtual void serializeJsonOptions(JsonSerializeFormat & handler);
virtual void writeJsonOptions(JsonNode & json) const;
///Loads object-type specific options void serializeJsonOwner(JsonSerializeFormat & handler);
///(!) do not forget to call inherited method first when overriding
virtual void readJsonOptions(const JsonNode & json);
void writeOwner(JsonNode & json) const;
void readOwner(const JsonNode & json);
private: private:
mutable std::string stringId;///<alternate id, dynamically generated, do not serialize mutable std::string stringId;///<alternate id, dynamically generated, do not serialize
}; };

View File

@@ -23,6 +23,7 @@
#include "../CGameState.h" #include "../CGameState.h"
#include "../mapping/CMap.h" #include "../mapping/CMap.h"
#include "../CPlayerState.h" #include "../CPlayerState.h"
#include "../serializer/JsonSerializeFormat.h"
std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist; std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist;
ui8 CGObelisk::obeliskCount = 0; //how many obelisks are on map ui8 CGObelisk::obeliskCount = 0; //how many obelisks are on map
@@ -593,59 +594,60 @@ void CGCreature::giveReward(const CGHeroInstance * h) const
} }
} }
static const std::string CHARACTER_JSON [] = static const std::vector<std::string> CHARACTER_JSON =
{ {
"compliant", "friendly", "aggressive", "hostile", "savage" "compliant", "friendly", "aggressive", "hostile", "savage"
}; };
void CGCreature::writeJsonOptions(JsonNode& json) const void CGCreature::serializeJsonOptions(JsonSerializeFormat & handler)
{ {
assert(vstd::iswithin(character, 0, 4)); handler.serializeNumericEnum("character", CHARACTER_JSON, (si8)0, character);
json["character"].String() = CHARACTER_JSON[character];
if(handler.saving)
{
if(hasStackAtSlot(SlotID(0))) if(hasStackAtSlot(SlotID(0)))
{ {
const auto & sta = getStack(SlotID(0)); si32 amount = getStack(SlotID(0)).count;
json["amount"].Float() = sta.count; handler.serializeNumeric("amount", amount);
} }
json["noGrowing"].Bool() = notGrowingTeam;
json["neverFlees"].Bool() = neverFlees;
json["rewardMessage"].String() = message;
json["rewardArtifact"].String() = (gainedArtifact == ArtifactID(ArtifactID::NONE) ? "" : gainedArtifact.toArtifact()->identifier);
if(resources.nonZero()) if(resources.nonZero())
{ {
for(size_t idx = 0; idx < resources.size(); idx++) for(size_t idx = 0; idx < resources.size(); idx++)
json["rewardResources"][GameConstants::RESOURCE_NAMES[idx]].Float() = resources[idx]; handler.getCurrent()["rewardResources"][GameConstants::RESOURCE_NAMES[idx]].Float() = resources[idx];
}
} }
void CGCreature::readJsonOptions(const JsonNode& json) auto tmp = (gainedArtifact == ArtifactID(ArtifactID::NONE) ? "" : gainedArtifact.toArtifact()->identifier);
handler.serializeString("rewardArtifact", tmp);
}
else
{ {
character = vstd::find_pos(CHARACTER_JSON,json["character"].String()); si32 amount = 0;
vstd::amin(character, 0); handler.serializeNumeric("amount", amount);
auto hlp = new CStackInstance(); auto hlp = new CStackInstance();
hlp->count = json["amount"].Float(); hlp->count = amount;
//type will be set during initialization //type will be set during initialization
putStack(SlotID(0), hlp); putStack(SlotID(0), hlp);
notGrowingTeam = json["noGrowing"].Bool();
neverFlees = json["neverFlees"].Bool();
message = json["rewardMessage"].String();
gainedArtifact = ArtifactID(ArtifactID::NONE);
if(json["rewardArtifact"].String() != "")
{ {
auto artid = VLC->modh->identifiers.getIdentifier("core", "artifact", json["rewardArtifact"].String()); TResources tmp(handler.getCurrent()["rewardResources"]);
std::swap(tmp,resources);
}
{
gainedArtifact = ArtifactID(ArtifactID::NONE);
std::string tmp;
handler.serializeString("rewardArtifact", tmp);
if(tmp != "")
{
auto artid = VLC->modh->identifiers.getIdentifier("core", "artifact", tmp);
if(artid) if(artid)
gainedArtifact = ArtifactID(artid.get()); gainedArtifact = ArtifactID(artid.get());
} }
}
TResources tmp(json["rewardResources"]); }
std::swap(tmp,resources); handler.serializeBool("noGrowing", notGrowingTeam);
handler.serializeBool("neverFlees", neverFlees);
handler.serializeString("rewardMessage", message);
} }
//CGMine //CGMine
@@ -790,14 +792,18 @@ void CGMine::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) con
cb->startBattleI(hero, this); cb->startBattleI(hero, this);
} }
void CGMine::writeJsonOptions(JsonNode & json) const void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
{ {
CCreatureSet::writeJson(json["army"]); CCreatureSet::serializeJson(handler, "army");
if(isAbandoned()) if(isAbandoned())
{ {
JsonNode & node = json["possibleResources"]; auto possibleResources = handler.enterStruct("possibleResources");
JsonNode & node = handler.getCurrent();
if(handler.saving)
{
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++) for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
if(tempOwner.getNum() & 1<<i) if(tempOwner.getNum() & 1<<i)
{ {
@@ -808,18 +814,6 @@ void CGMine::writeJsonOptions(JsonNode & json) const
} }
else else
{ {
CGObjectInstance::writeOwner(json);
}
}
void CGMine::readJsonOptions(const JsonNode & json)
{
CCreatureSet::readJson(json["army"]);
if(isAbandoned())
{
const JsonNode & node = json["possibleResources"];
std::set<int> possibleResources; std::set<int> possibleResources;
if(node.Vector().size() == 0) if(node.Vector().size() == 0)
@@ -848,13 +842,13 @@ void CGMine::readJsonOptions(const JsonNode & json)
tempOwner = PlayerColor(tmp); tempOwner = PlayerColor(tmp);
} }
} }
}
else else
{ {
CGObjectInstance::readOwner(json); serializeJsonOwner(handler);
} }
} }
std::string CGResource::getHoverText(PlayerColor player) const std::string CGResource::getHoverText(PlayerColor player) const
{ {
return VLC->generaltexth->restypes[subID]; return VLC->generaltexth->restypes[subID];
@@ -939,18 +933,11 @@ void CGResource::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
cb->startBattleI(hero, this); cb->startBattleI(hero, this);
} }
void CGResource::writeJsonOptions(JsonNode& json) const void CGResource::serializeJsonOptions(JsonSerializeFormat & handler)
{ {
CCreatureSet::writeJson(json["guards"]); CCreatureSet::serializeJson(handler, "guards");
json["amount"].Float() = amount; handler.serializeNumeric("amount", amount);
json["guardMessage"].String() = message; handler.serializeString("guardMessage", message);
}
void CGResource::readJsonOptions(const JsonNode& json)
{
CCreatureSet::readJson(json["guards"]);
amount = json["amount"].Float();
message = json["guardMessage"].String();
} }
CGTeleport::CGTeleport() : CGTeleport::CGTeleport() :
@@ -1439,25 +1426,21 @@ void CGArtifact::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
cb->startBattleI(hero, this); cb->startBattleI(hero, this);
} }
void CGArtifact::writeJsonOptions(JsonNode& json) const void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
{ {
CCreatureSet::writeJson(json["guards"]); handler.serializeString("guardMessage", message);
json["guardMessage"].String() = message; CCreatureSet::serializeJson(handler, "guards");
if(ID == Obj::SPELL_SCROLL)
if(handler.saving && ID == Obj::SPELL_SCROLL)
{ {
const Bonus * b = storedArtifact->getBonusLocalFirst(Selector::type(Bonus::SPELL)); const Bonus * b = storedArtifact->getBonusLocalFirst(Selector::type(Bonus::SPELL));
SpellID spellId(b->subtype); SpellID spellId(b->subtype);
json["spell"].String() = SpellID(b->subtype).toSpell()->identifier; std::string spell = SpellID(b->subtype).toSpell()->identifier;
handler.serializeString("spell", spell);
} }
} }
void CGArtifact::readJsonOptions(const JsonNode& json)
{
CCreatureSet::readJson(json["guards"]);
message = json["guardMessage"].String();
}
void CGWitchHut::initObj() void CGWitchHut::initObj()
{ {
if (allowedAbilities.empty()) //this can happen for RMG. regular maps load abilities from map file if (allowedAbilities.empty()) //this can happen for RMG. regular maps load abilities from map file
@@ -1515,17 +1498,11 @@ std::string CGWitchHut::getHoverText(const CGHeroInstance * hero) const
return hoverName; return hoverName;
} }
void CGWitchHut::writeJsonOptions(JsonNode& json) const void CGWitchHut::serializeJsonOptions(JsonSerializeFormat & handler)
{ {
//todo:CGWitchHut::serializeJsonOptions
} }
void CGWitchHut::readJsonOptions(const JsonNode& json)
{
}
void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const
{ {
int message; int message;
@@ -1665,23 +1642,9 @@ std::string CGShrine::getHoverText(const CGHeroInstance * hero) const
return hoverName; return hoverName;
} }
void CGShrine::writeJsonOptions(JsonNode& json) const void CGShrine::serializeJsonOptions(JsonSerializeFormat& handler)
{ {
if(spell != SpellID::NONE) handler.serializeId("spell", &CSpellHandler::decodeSpell, &CSpellHandler::encodeSpell, SpellID(SpellID::NONE), spell);
{
json["spell"].String() = spell.toSpell()->identifier;
}
}
void CGShrine::readJsonOptions(const JsonNode& json)
{
spell = SpellID::NONE;
if(json["spell"].String() != "")
{
auto raw = VLC->modh->identifiers.getIdentifier("core", "spell",json["spell"].String());
if(raw)
spell = SpellID(raw.get());
}
} }
void CGSignBottle::initObj() void CGSignBottle::initObj()
@@ -1710,14 +1673,9 @@ void CGSignBottle::onHeroVisit( const CGHeroInstance * h ) const
cb->removeObject(this); cb->removeObject(this);
} }
void CGSignBottle::writeJsonOptions(JsonNode& json) const void CGSignBottle::serializeJsonOptions(JsonSerializeFormat& handler)
{ {
json["text"].String() = message; handler.serializeString("text", message);
}
void CGSignBottle::readJsonOptions(const JsonNode& json)
{
message = json["text"].String();
} }
void CGScholar::onHeroVisit( const CGHeroInstance * h ) const void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
@@ -1793,7 +1751,10 @@ void CGScholar::initObj()
} }
} }
void CGScholar::writeJsonOptions(JsonNode& json) const void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler)
{
JsonNode& json = handler.getCurrent();
if(handler.saving)
{ {
switch(bonusType) switch(bonusType)
{ {
@@ -1810,8 +1771,7 @@ void CGScholar::writeJsonOptions(JsonNode& json) const
break; break;
} }
} }
else
void CGScholar::readJsonOptions(const JsonNode& json)
{ {
bonusType = RANDOM; bonusType = RANDOM;
if(json["rewardPrimSkill"].String() != "") if(json["rewardPrimSkill"].String() != "")
@@ -1842,6 +1802,7 @@ void CGScholar::readJsonOptions(const JsonNode& json)
} }
} }
} }
}
void CGGarrison::onHeroVisit (const CGHeroInstance *h) const void CGGarrison::onHeroVisit (const CGHeroInstance *h) const
{ {
@@ -1879,18 +1840,11 @@ void CGGarrison::battleFinished(const CGHeroInstance *hero, const BattleResult &
onHeroVisit(hero); onHeroVisit(hero);
} }
void CGGarrison::writeJsonOptions(JsonNode& json) const void CGGarrison::serializeJsonOptions(JsonSerializeFormat& handler)
{ {
CCreatureSet::writeJson(json["army"]); handler.serializeBool("removableUnits", removableUnits);
CGObjectInstance::writeOwner(json); serializeJsonOwner(handler);
json["removableUnits"].Bool() = removableUnits; CCreatureSet::serializeJson(handler, "army");
}
void CGGarrison::readJsonOptions(const JsonNode& json)
{
CCreatureSet::readJson(json["army"]);
CGObjectInstance::readOwner(json);
removableUnits = json["removableUnits"].Bool();
} }
void CGMagi::initObj() void CGMagi::initObj()
@@ -2030,14 +1984,9 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
} }
} }
void CGShipyard::writeJsonOptions(JsonNode& json) const void CGShipyard::serializeJsonOptions(JsonSerializeFormat& handler)
{ {
CGObjectInstance::writeOwner(json); serializeJsonOwner(handler);
}
void CGShipyard::readJsonOptions(const JsonNode& json)
{
CGObjectInstance::readOwner(json);
} }
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
@@ -2222,12 +2171,7 @@ void CGLighthouse::giveBonusTo( PlayerColor player ) const
cb->sendAndApply(&gb); cb->sendAndApply(&gb);
} }
void CGLighthouse::writeJsonOptions(JsonNode& json) const void CGLighthouse::serializeJsonOptions(JsonSerializeFormat& handler)
{ {
CGObjectInstance::writeOwner(json); serializeJsonOwner(handler);
}
void CGLighthouse::readJsonOptions(const JsonNode& json)
{
CGObjectInstance::readOwner(json);
} }

View File

@@ -86,11 +86,9 @@ public:
} }
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ui8 what, ui32 val) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override;
void writeJsonOptions(JsonNode & json) const override;
void readJsonOptions(const JsonNode & json) override;
private: private:
void fight(const CGHeroInstance *h) const; void fight(const CGHeroInstance *h) const;
void flee( const CGHeroInstance * h ) const; void flee( const CGHeroInstance * h ) const;
void fleeDecision(const CGHeroInstance *h, ui32 pursue) const; void fleeDecision(const CGHeroInstance *h, ui32 pursue) const;
@@ -101,7 +99,6 @@ private:
}; };
class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles
{ {
public: public:
@@ -116,8 +113,7 @@ public:
h & message; h & message;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGWitchHut : public CPlayersVisited class DLL_LINKAGE CGWitchHut : public CPlayersVisited
@@ -136,8 +132,7 @@ public:
h & allowedAbilities & ability; h & allowedAbilities & ability;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGScholar : public CGObjectInstance class DLL_LINKAGE CGScholar : public CGObjectInstance
@@ -156,8 +151,7 @@ public:
h & bonusType & bonusID; h & bonusType & bonusID;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGGarrison : public CArmedInstance class DLL_LINKAGE CGGarrison : public CArmedInstance
@@ -175,8 +169,7 @@ public:
h & removableUnits; h & removableUnits;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGArtifact : public CArmedInstance class DLL_LINKAGE CGArtifact : public CArmedInstance
@@ -202,8 +195,7 @@ public:
h & message & storedArtifact; h & message & storedArtifact;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGResource : public CArmedInstance class DLL_LINKAGE CGResource : public CArmedInstance
@@ -227,8 +219,7 @@ public:
h & amount & message; h & amount & message;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGShrine : public CPlayersVisited class DLL_LINKAGE CGShrine : public CPlayersVisited
@@ -246,8 +237,7 @@ public:
h & spell; h & spell;
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGMine : public CArmedInstance class DLL_LINKAGE CGMine : public CArmedInstance
@@ -277,8 +267,7 @@ public:
} }
ui32 defaultResProduction(); ui32 defaultResProduction();
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
struct DLL_LINKAGE TeleportChannel struct DLL_LINKAGE TeleportChannel
@@ -444,8 +433,7 @@ public:
h & static_cast<IShipyard&>(*this); h & static_cast<IShipyard&>(*this);
} }
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };
class DLL_LINKAGE CGMagi : public CGObjectInstance class DLL_LINKAGE CGMagi : public CGObjectInstance
@@ -462,8 +450,6 @@ public:
} }
}; };
class DLL_LINKAGE CCartographer : public CPlayersVisited class DLL_LINKAGE CCartographer : public CPlayersVisited
{ {
///behaviour varies depending on surface and floor ///behaviour varies depending on surface and floor
@@ -515,6 +501,5 @@ public:
} }
void giveBonusTo( PlayerColor player ) const; void giveBonusTo( PlayerColor player ) const;
protected: protected:
void writeJsonOptions(JsonNode & json) const override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void readJsonOptions(const JsonNode & json) override;
}; };

View File

@@ -525,7 +525,7 @@ std::unique_ptr<CMapHeader> CMapLoaderJson::loadMapHeader()
return std::move(result); return std::move(result);
} }
const JsonNode CMapLoaderJson::getFromArchive(const std::string & archiveFilename) JsonNode CMapLoaderJson::getFromArchive(const std::string & archiveFilename)
{ {
ResourceID resource(archiveFilename, EResType::TEXT); ResourceID resource(archiveFilename, EResType::TEXT);
@@ -747,7 +747,7 @@ void CMapLoaderJson::readTerrain()
} }
CMapLoaderJson::MapObjectLoader::MapObjectLoader(CMapLoaderJson * _owner, const JsonMap::value_type& json): CMapLoaderJson::MapObjectLoader::MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type& json):
owner(_owner), instance(nullptr),id(-1), jsonKey(json.first), configuration(json.second), internalId(extractNumber(jsonKey, '_')) owner(_owner), instance(nullptr),id(-1), jsonKey(json.first), configuration(json.second), internalId(extractNumber(jsonKey, '_'))
{ {
@@ -797,7 +797,9 @@ void CMapLoaderJson::MapObjectLoader::configure()
if(nullptr == instance) if(nullptr == instance)
return; return;
instance->readJson(configuration); JsonDeserializer handler(configuration);
instance->serializeJson(handler);
if(instance->ID == Obj::TOWN) if(instance->ID == Obj::TOWN)
{ {
@@ -841,10 +843,10 @@ void CMapLoaderJson::readObjects()
std::vector<std::unique_ptr<MapObjectLoader>> loaders;//todo: optimize MapObjectLoader memory layout std::vector<std::unique_ptr<MapObjectLoader>> loaders;//todo: optimize MapObjectLoader memory layout
const JsonNode data = getFromArchive(OBJECTS_FILE_NAME); JsonNode data = getFromArchive(OBJECTS_FILE_NAME);
//get raw data //get raw data
for(const auto & p : data.Struct()) for(auto & p : data.Struct())
loaders.push_back(vstd::make_unique<MapObjectLoader>(this, p)); loaders.push_back(vstd::make_unique<MapObjectLoader>(this, p));
auto sortInfos = [](const std::unique_ptr<MapObjectLoader> & lhs, const std::unique_ptr<MapObjectLoader> & rhs) -> bool auto sortInfos = [](const std::unique_ptr<MapObjectLoader> & lhs, const std::unique_ptr<MapObjectLoader> & rhs) -> bool
@@ -993,8 +995,14 @@ void CMapSaverJson::writeObjects()
{ {
JsonNode data(JsonNode::DATA_STRUCT); JsonNode data(JsonNode::DATA_STRUCT);
for(const CGObjectInstance * obj : map->objects) JsonSerializer handler(data);
obj->writeJson(data[obj->getStringId()]);
for(CGObjectInstance * obj : map->objects)
{
auto temp = handler.enterStruct(obj->getStringId());
obj->serializeJson(handler);
}
if(map->grailPos.valid()) if(map->grailPos.valid())
{ {
@@ -1010,7 +1018,6 @@ void CMapSaverJson::writeObjects()
std::string grailId = boost::str(boost::format("grail_%d") % map->objects.size()); std::string grailId = boost::str(boost::format("grail_%d") % map->objects.size());
data[grailId] = grail; data[grailId] = grail;
} }
addToArchive(data, OBJECTS_FILE_NAME); addToArchive(data, OBJECTS_FILE_NAME);

View File

@@ -159,12 +159,12 @@ private:
struct MapObjectLoader struct MapObjectLoader
{ {
MapObjectLoader(CMapLoaderJson * _owner, const JsonMap::value_type & json); MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type & json);
CMapLoaderJson * owner; CMapLoaderJson * owner;
CGObjectInstance * instance; CGObjectInstance * instance;
ObjectInstanceID id; ObjectInstanceID id;
std::string jsonKey;//full id defined by map creator std::string jsonKey;//full id defined by map creator
const JsonNode & configuration; JsonNode & configuration;
si32 internalId;//unique part of id defined by map creator (also = quest identifier) si32 internalId;//unique part of id defined by map creator (also = quest identifier)
///constructs object (without configuration) ///constructs object (without configuration)
void construct(); void construct();
@@ -197,7 +197,7 @@ private:
*/ */
void readObjects(); void readObjects();
const JsonNode getFromArchive(const std::string & archiveFilename); JsonNode getFromArchive(const std::string & archiveFilename);
CInputStream * buffer; CInputStream * buffer;
std::shared_ptr<CIOApi> ioApi; std::shared_ptr<CIOApi> ioApi;

View File

@@ -48,6 +48,24 @@ void JsonDeserializer::serializeIntEnum(const std::string & fieldName, const std
value = rawValue; value = rawValue;
} }
void JsonDeserializer::serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value)
{
std::string identifier;
serializeString(fieldName, identifier);
if(identifier == "")
{
value = defaultValue;
return;
}
si32 rawId = decoder(identifier);
if(rawId >= 0)
value = rawId;
else
value = defaultValue;
}
void JsonDeserializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value) void JsonDeserializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value)
{ {
const JsonNode & field = current->operator[](fieldName); const JsonNode & field = current->operator[](fieldName);

View File

@@ -27,4 +27,5 @@ public:
protected: protected:
void serializeFloat(const std::string & fieldName, double & value) override; void serializeFloat(const std::string & fieldName, double & value) override;
void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) override; void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) override;
void serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) override;
}; };

View File

@@ -98,6 +98,16 @@ public:
virtual void serializeString(const std::string & fieldName, std::string & value) = 0; virtual void serializeString(const std::string & fieldName, std::string & value) = 0;
template <typename T>
void serializeId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const T & defaultValue, T & value)
{
const si32 tempDefault = defaultValue.num;
si32 tempValue = value.num;
serializeIntId(fieldName, decoder, encoder, tempDefault, tempValue);
if(!saving)
value = T(tempValue);
}
protected: protected:
JsonNode * root; JsonNode * root;
JsonNode * current; JsonNode * current;
@@ -107,6 +117,8 @@ protected:
virtual void serializeFloat(const std::string & fieldName, double & value) = 0; virtual void serializeFloat(const std::string & fieldName, double & value) = 0;
virtual void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) = 0; virtual void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) = 0;
virtual void serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) = 0;
private: private:
friend class JsonStructSerializer; friend class JsonStructSerializer;
}; };

View File

@@ -40,6 +40,15 @@ void JsonSerializer::serializeIntEnum(const std::string & fieldName, const std::
current->operator[](fieldName).String() = enumMap.at(value); current->operator[](fieldName).String() = enumMap.at(value);
} }
void JsonSerializer::serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32& value)
{
if(defaultValue == value)
return;
std::string identifier = encoder(value);
serializeString(fieldName, identifier);
}
void JsonSerializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value) void JsonSerializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value)
{ {
assert(standard.size() == value.size()); assert(standard.size() == value.size());

View File

@@ -27,4 +27,5 @@ public:
protected: protected:
void serializeFloat(const std::string & fieldName, double & value) override; void serializeFloat(const std::string & fieldName, double & value) override;
void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) override; void serializeIntEnum(const std::string & fieldName, const std::vector<std::string> & enumMap, const si32 defaultValue, si32 & value) override;
void serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) override;
}; };