mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Use JsonSerializeFormat for map objects
This commit is contained in:
		| @@ -11,6 +11,7 @@ | ||||
| #include "spells/CSpellHandler.h" | ||||
| #include "CHeroHandler.h" | ||||
| #include "IBonusTypeHandler.h" | ||||
| #include "serializer/JsonSerializeFormat.h" | ||||
|  | ||||
| /* | ||||
|  * CCreatureSet.cpp, part of VCMI engine | ||||
| @@ -479,27 +480,34 @@ CCreatureSet & CCreatureSet::operator=(const CCreatureSet&cs) | ||||
|  | ||||
| void CCreatureSet::armyChanged() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void CCreatureSet::writeJson(JsonNode& json) const | ||||
| void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName) | ||||
| { | ||||
| 	for(const auto & p : stacks) | ||||
| 	if(handler.saving && stacks.empty()) | ||||
| 		return; | ||||
| 	JsonNode & json = handler.getCurrent()[fieldName]; | ||||
|  | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 		JsonNode stack_node; | ||||
| 		p.second->writeJson(stack_node); | ||||
| 		json.Vector()[p.first.getNum()] = stack_node; | ||||
| 		for(const auto & p : stacks) | ||||
| 		{ | ||||
| 			JsonNode stack_node; | ||||
| 			p.second->writeJson(stack_node); | ||||
| 			json.Vector()[p.first.getNum()] = stack_node; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CCreatureSet::readJson(const JsonNode& json) | ||||
| { | ||||
| 	for(size_t idx = 0; idx < json.Vector().size(); idx++) | ||||
| 	else | ||||
| 	{ | ||||
| 		CStackInstance * new_stack = new CStackInstance(); | ||||
| 		for(size_t idx = 0; idx < json.Vector().size(); idx++) | ||||
| 		{ | ||||
| 			CStackInstance * new_stack = new CStackInstance(); | ||||
|  | ||||
| 		new_stack->readJson(json.Vector()[idx]); | ||||
| 			new_stack->readJson(json.Vector()[idx]); | ||||
|  | ||||
| 		putStack(SlotID(idx), new_stack); | ||||
| 			putStack(SlotID(idx), new_stack); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ class CCreature; | ||||
| class CGHeroInstance; | ||||
| class CArmedInstance; | ||||
| class CCreatureArtifactSet; | ||||
| class JsonSerializeFormat; | ||||
|  | ||||
| class DLL_LINKAGE CStackBasicDescriptor | ||||
| { | ||||
| @@ -220,10 +221,7 @@ public: | ||||
| 		h & stacks & formation; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	void writeJson(JsonNode & json) const; | ||||
|  | ||||
| 	void readJson(const JsonNode & json); | ||||
| 	void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName); | ||||
|  | ||||
| 	operator bool() const | ||||
| 	{ | ||||
|   | ||||
| @@ -132,13 +132,3 @@ CBonusSystemNode * CArmedInstance::whatShouldBeAttached() | ||||
| { | ||||
| 	return this; | ||||
| } | ||||
|  | ||||
| void CArmedInstance::writeJsonOptions(JsonNode& json) const | ||||
| { | ||||
| 	CGObjectInstance::writeJsonOptions(json); | ||||
| } | ||||
|  | ||||
| void CArmedInstance::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	CGObjectInstance::readJsonOptions(json); | ||||
| } | ||||
|   | ||||
| @@ -40,7 +40,4 @@ public: | ||||
| 		h & static_cast<CBonusSystemNode&>(*this); | ||||
| 		h & static_cast<CCreatureSet&>(*this); | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| }; | ||||
|   | ||||
| @@ -25,6 +25,7 @@ | ||||
| #include "../CTownHandler.h" | ||||
| #include "../mapping/CMap.h" | ||||
| #include "CGTownInstance.h" | ||||
| #include "../serializer/JsonSerializeFormat.h" | ||||
|  | ||||
| ///helpers | ||||
| static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const ui16 soundID) | ||||
| @@ -1470,42 +1471,47 @@ bool CGHeroInstance::hasVisions(const CGObjectInstance * target, const int subty | ||||
| 	return (distance < visionsRange) && (target->pos.z == pos.z); | ||||
| } | ||||
|  | ||||
| void CGHeroInstance::writeJsonOptions(JsonNode& json) const | ||||
| void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat& handler) | ||||
| { | ||||
| 	if(type) | ||||
| 	serializeJsonOwner(handler); | ||||
|  | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 		json["type"].String() = type->identifier; | ||||
| 		if(type) | ||||
| 		{ | ||||
| 			handler.serializeString("type", type->identifier); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			auto temp = VLC->heroh->heroes[subID]->identifier; | ||||
| 			handler.serializeString("type", temp); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		json["type"].String() = VLC->heroh->heroes[subID]->identifier; | ||||
| 		if(ID == Obj::HERO || ID == Obj::PRISON) | ||||
| 		{ | ||||
| 			std::string typeName; | ||||
| 			handler.serializeString("type", typeName); | ||||
|  | ||||
| 			auto rawId = VLC->modh->identifiers.getIdentifier("core", "hero", typeName); | ||||
|  | ||||
| 			if(rawId) | ||||
| 				subID = rawId.get(); | ||||
| 			else | ||||
| 				subID = 0; //fallback to Orrin, throw error instead? | ||||
| 		} | ||||
| 	} | ||||
| 	CCreatureSet::serializeJson(handler, "army"); | ||||
|  | ||||
| 	CGObjectInstance::writeOwner(json); | ||||
|  | ||||
| 	CCreatureSet::writeJson(json["army"]); | ||||
| 	CArtifactSet::writeJson(json["artifacts"]); | ||||
|  | ||||
| } | ||||
|  | ||||
| void CGHeroInstance::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	if(ID == Obj::HERO || ID == Obj::PRISON) | ||||
| 	{ | ||||
| 		auto typeName = json["type"].String(); | ||||
|  | ||||
| 		auto rawId = VLC->modh->identifiers.getIdentifier("core", "hero", typeName); | ||||
|  | ||||
| 		if(rawId) | ||||
| 			subID = rawId.get(); | ||||
| 		auto artifacts = handler.enterStruct("artifacts"); | ||||
| 		if(handler.saving) | ||||
| 			CArtifactSet::writeJson(handler.getCurrent()); | ||||
| 		else | ||||
| 			subID = 0; //fallback to Orrin, throw error instead? | ||||
| 			CArtifactSet::readJson(handler.getCurrent()); | ||||
| 	} | ||||
|  | ||||
| 	CGObjectInstance::readOwner(json); | ||||
|  | ||||
| 	CCreatureSet::readJson(json["army"]); | ||||
| 	CArtifactSet::readJson(json["artifacts"]); | ||||
| } | ||||
|  | ||||
| bool CGHeroInstance::isMissionCritical() const | ||||
|   | ||||
| @@ -251,8 +251,7 @@ public: | ||||
| 	std::string getObjectName() const override; | ||||
| protected: | ||||
| 	void setPropertyDer(ui8 what, ui32 val) override;//synchr | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
|  | ||||
| private: | ||||
| 	void levelUpAutomatically(); | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "../CGameState.h" | ||||
| #include "../mapping/CMapDefines.h" | ||||
| #include "../CPlayerState.h" | ||||
| #include "../serializer/JsonSerializeFormat.h" | ||||
|  | ||||
| std::vector<const CArtifact *> CGTownInstance::merchantArtifacts; | ||||
| 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) | ||||
| 		CGObjectInstance::writeOwner(json); | ||||
| } | ||||
|  | ||||
| void CGDwelling::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	//todo:CGDwelling::readJsonOptions | ||||
| 	if(ID != Obj::WAR_MACHINE_FACTORY && ID != Obj::REFUGEE_CAMP) | ||||
| 		CGObjectInstance::readOwner(json); | ||||
| 		serializeJsonOwner(handler); | ||||
| } | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	ID = index; | ||||
|   | ||||
| @@ -53,8 +53,7 @@ public: | ||||
| 	TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount> | ||||
|  | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
|  | ||||
| private: | ||||
| 	void initObj() override; | ||||
| @@ -256,4 +255,5 @@ public: | ||||
| 	std::string getObjectName() const override; | ||||
| protected: | ||||
| 	void setPropertyDer(ui8 what, ui32 val) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|   | ||||
| @@ -24,6 +24,8 @@ | ||||
| #include "CObjectClassesHandler.h" | ||||
| #include "CGTownInstance.h" | ||||
|  | ||||
| #include "../serializer/JsonSerializeFormat.h" | ||||
|  | ||||
| IGameCallback * IObjectInterface::cb = nullptr; | ||||
|  | ||||
| ///helpers | ||||
| @@ -331,64 +333,70 @@ bool CGObjectInstance::passableFor(PlayerColor color) const | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::writeJson(JsonNode & json) const | ||||
| void CGObjectInstance::serializeJson(JsonSerializeFormat & handler) | ||||
| { | ||||
| 	logGlobal->debugStream() <<"Save: [" << pos << "] " << id << " " << ID << " " << subID << " " << typeName << " " << subTypeName; | ||||
|  | ||||
| 	json.setType(JsonNode::DATA_STRUCT); | ||||
| 	json["type"].String() = typeName; | ||||
| 	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) | ||||
| { | ||||
| 	if(json.getType() != JsonNode::DATA_STRUCT) | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 		logGlobal->error("Invalid object instance data"); | ||||
| 		return; | ||||
| 		handler.serializeString("type", typeName); | ||||
| 		handler.serializeString("subType", subTypeName); | ||||
| 	} | ||||
| 	pos.x = json["x"].Float(); | ||||
| 	pos.y = json["y"].Float(); | ||||
| 	pos.z = json["l"].Float(); | ||||
|  | ||||
| 	appearance.readJson(json["template"], false); | ||||
| 	handler.serializeNumeric("x", pos.x); | ||||
| 	handler.serializeNumeric("y", pos.y); | ||||
| 	handler.serializeNumeric("l", pos.z); | ||||
|  | ||||
| 	readJsonOptions(json["options"]); | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::writeJsonOptions(JsonNode & json) const | ||||
| { | ||||
| 	json.setType(JsonNode::DATA_STRUCT); | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::readJsonOptions(const JsonNode & json) | ||||
| { | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::writeOwner(JsonNode & json) const | ||||
| { | ||||
| 	if(tempOwner.isValidPlayer()) | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 		json["owner"].String() = GameConstants::PLAYER_COLOR_NAMES[tempOwner.getNum()]; | ||||
| 		appearance.writeJson(handler.getCurrent()["template"], false); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		appearance.readJson(handler.getCurrent()["template"], false); | ||||
| 	} | ||||
|  | ||||
| 	{ | ||||
| 		auto options = handler.enterStruct("options"); | ||||
| 		serializeJsonOptions(handler); | ||||
| 	} | ||||
|  | ||||
| 	if(handler.saving && handler.getCurrent()["options"].isNull()) | ||||
| 	{ | ||||
| 		handler.getCurrent().Struct().erase("options"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::readOwner(const JsonNode & json) | ||||
| void CGObjectInstance::serializeJsonOptions(JsonSerializeFormat & handler) | ||||
| { | ||||
| 	tempOwner = PlayerColor::NEUTRAL;//this method assumes that object is ownable | ||||
| 	if(json["owner"].getType() == JsonNode::DATA_STRING) | ||||
|  | ||||
| } | ||||
|  | ||||
| void CGObjectInstance::serializeJsonOwner(JsonSerializeFormat & handler) | ||||
| { | ||||
| 	std::string temp; | ||||
|  | ||||
| 	//todo: use enum serialize | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 		auto rawOwner = vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, json["owner"].String()); | ||||
| 		if(rawOwner >=0) | ||||
| 			tempOwner = PlayerColor(rawOwner); | ||||
| 		else | ||||
| 			logGlobal->errorStream() << "Invalid owner :" << json["owner"].String(); | ||||
| 		if(tempOwner.isValidPlayer()) | ||||
| 		{ | ||||
| 			temp = GameConstants::PLAYER_COLOR_NAMES[tempOwner.getNum()]; | ||||
| 			handler.serializeString("owner", temp); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		tempOwner = PlayerColor::NEUTRAL;//this method assumes that object is ownable | ||||
|  | ||||
| 		handler.serializeString("owner", temp); | ||||
|  | ||||
| 		if(temp != "") | ||||
| 		{ | ||||
| 			auto rawOwner = vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, temp); | ||||
| 			if(rawOwner >=0) | ||||
| 				tempOwner = PlayerColor(rawOwner); | ||||
| 			else | ||||
| 				logGlobal->errorStream() << "Invalid owner :" << temp; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class IGameCallback; | ||||
| class CGObjectInstance; | ||||
| struct MetaString; | ||||
| struct BattleResult; | ||||
| class JsonSerializeFormat; | ||||
|  | ||||
| // 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 | ||||
| @@ -186,10 +187,7 @@ public: | ||||
| 	} | ||||
|  | ||||
| 	///Entry point of Json serialization | ||||
| 	void writeJson(JsonNode & json) const; | ||||
|  | ||||
| 	///Entry point of Json de-serialization | ||||
| 	void readJson(const JsonNode & json); | ||||
| 	void serializeJson(JsonSerializeFormat & handler); | ||||
|  | ||||
| protected: | ||||
| 	/// 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 | ||||
| 	void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const; | ||||
|  | ||||
| 	///Saves object-type specific options | ||||
| 	///(!) do not forget to call inherited method first when overriding | ||||
| 	virtual void writeJsonOptions(JsonNode & json) const; | ||||
| 	///Serialize object-type specific options | ||||
| 	virtual void serializeJsonOptions(JsonSerializeFormat & handler); | ||||
|  | ||||
| 	///Loads object-type specific options | ||||
| 	///(!) do not forget to call inherited method  first when overriding | ||||
| 	virtual void readJsonOptions(const JsonNode & json); | ||||
| 	void serializeJsonOwner(JsonSerializeFormat & handler); | ||||
|  | ||||
| 	void writeOwner(JsonNode & json) const; | ||||
| 	void readOwner(const JsonNode & json); | ||||
| private: | ||||
| 	mutable std::string stringId;///<alternate id, dynamically generated, do not serialize | ||||
| }; | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #include "../CGameState.h" | ||||
| #include "../mapping/CMap.h" | ||||
| #include "../CPlayerState.h" | ||||
| #include "../serializer/JsonSerializeFormat.h" | ||||
|  | ||||
| std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist; | ||||
| 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" | ||||
| }; | ||||
|  | ||||
| void CGCreature::writeJsonOptions(JsonNode& json) const | ||||
| void CGCreature::serializeJsonOptions(JsonSerializeFormat & handler) | ||||
| { | ||||
| 	assert(vstd::iswithin(character, 0, 4)); | ||||
| 	json["character"].String() = CHARACTER_JSON[character]; | ||||
| 	handler.serializeNumericEnum("character", CHARACTER_JSON, (si8)0, character); | ||||
|  | ||||
| 	if(hasStackAtSlot(SlotID(0))) | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 		const auto & sta = getStack(SlotID(0)); | ||||
| 		json["amount"].Float() = sta.count; | ||||
| 		if(hasStackAtSlot(SlotID(0))) | ||||
| 		{ | ||||
| 			si32 amount = getStack(SlotID(0)).count; | ||||
| 			handler.serializeNumeric("amount", amount); | ||||
| 		} | ||||
|  | ||||
| 		if(resources.nonZero()) | ||||
| 		{ | ||||
| 			for(size_t idx = 0; idx < resources.size(); idx++) | ||||
| 				handler.getCurrent()["rewardResources"][GameConstants::RESOURCE_NAMES[idx]].Float() = resources[idx]; | ||||
| 		} | ||||
|  | ||||
| 		auto tmp = (gainedArtifact == ArtifactID(ArtifactID::NONE) ? "" : gainedArtifact.toArtifact()->identifier); | ||||
| 		handler.serializeString("rewardArtifact", tmp); | ||||
| 	} | ||||
|  | ||||
| 	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()) | ||||
| 	else | ||||
| 	{ | ||||
| 		for(size_t idx = 0; idx < resources.size(); idx++) | ||||
| 			json["rewardResources"][GameConstants::RESOURCE_NAMES[idx]].Float() = resources[idx]; | ||||
| 		si32 amount = 0; | ||||
| 		handler.serializeNumeric("amount", amount); | ||||
| 		auto  hlp = new CStackInstance(); | ||||
| 		hlp->count = amount; | ||||
| 		//type will be set during initialization | ||||
| 		putStack(SlotID(0), hlp); | ||||
| 		{ | ||||
| 			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) | ||||
| 					gainedArtifact = ArtifactID(artid.get()); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGCreature::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	character = vstd::find_pos(CHARACTER_JSON,json["character"].String()); | ||||
| 	vstd::amin(character, 0); | ||||
|  | ||||
| 	auto  hlp = new CStackInstance(); | ||||
| 	hlp->count = json["amount"].Float(); | ||||
| 	//type will be set during initialization | ||||
| 	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()); | ||||
| 		if(artid) | ||||
| 			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 | ||||
| @@ -790,71 +792,63 @@ void CGMine::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) con | ||||
| 		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()) | ||||
| 	{ | ||||
| 		JsonNode & node = json["possibleResources"]; | ||||
| 		auto possibleResources = handler.enterStruct("possibleResources"); | ||||
|  | ||||
| 		for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++) | ||||
| 			if(tempOwner.getNum() & 1<<i) | ||||
| 			{ | ||||
| 				JsonNode one(JsonNode::DATA_STRING); | ||||
| 				one.String() = GameConstants::RESOURCE_NAMES[i]; | ||||
| 				node.Vector().push_back(one); | ||||
| 			} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		CGObjectInstance::writeOwner(json); | ||||
| 	} | ||||
| } | ||||
| 		JsonNode & node = handler.getCurrent(); | ||||
|  | ||||
| void CGMine::readJsonOptions(const JsonNode & json) | ||||
| { | ||||
| 	CCreatureSet::readJson(json["army"]); | ||||
|  | ||||
| 	if(isAbandoned()) | ||||
| 	{ | ||||
| 		const JsonNode & node = json["possibleResources"]; | ||||
|  | ||||
| 		std::set<int> possibleResources; | ||||
|  | ||||
| 		if(node.Vector().size() == 0) | ||||
| 		if(handler.saving) | ||||
| 		{ | ||||
| 			//assume all allowed | ||||
| 			for(int i = (int)Res::WOOD; i < (int) Res::GOLD; i++) | ||||
| 				possibleResources.insert(i); | ||||
| 			for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++) | ||||
| 				if(tempOwner.getNum() & 1<<i) | ||||
| 				{ | ||||
| 					JsonNode one(JsonNode::DATA_STRING); | ||||
| 					one.String() = GameConstants::RESOURCE_NAMES[i]; | ||||
| 					node.Vector().push_back(one); | ||||
| 				} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|             auto names = node.convertTo<std::vector<std::string>>(); | ||||
| 			std::set<int> possibleResources; | ||||
|  | ||||
|             for(const std::string & s : names) | ||||
| 			if(node.Vector().size() == 0) | ||||
| 			{ | ||||
|                 int raw_res = vstd::find_pos(GameConstants::RESOURCE_NAMES, s); | ||||
|                 if(raw_res < 0) | ||||
| 					logGlobal->errorStream() << "Invalid resource name: "+s; | ||||
| 				else | ||||
| 					possibleResources.insert(raw_res); | ||||
| 				//assume all allowed | ||||
| 				for(int i = (int)Res::WOOD; i < (int) Res::GOLD; i++) | ||||
| 					possibleResources.insert(i); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				auto names = node.convertTo<std::vector<std::string>>(); | ||||
|  | ||||
| 			int tmp = 0; | ||||
| 				for(const std::string & s : names) | ||||
| 				{ | ||||
| 					int raw_res = vstd::find_pos(GameConstants::RESOURCE_NAMES, s); | ||||
| 					if(raw_res < 0) | ||||
| 						logGlobal->errorStream() << "Invalid resource name: "+s; | ||||
| 					else | ||||
| 						possibleResources.insert(raw_res); | ||||
| 				} | ||||
|  | ||||
| 			for(int r : possibleResources) | ||||
| 				tmp |=  (1<<r); | ||||
| 			tempOwner = PlayerColor(tmp); | ||||
| 				int tmp = 0; | ||||
|  | ||||
| 				for(int r : possibleResources) | ||||
| 					tmp |=  (1<<r); | ||||
| 				tempOwner = PlayerColor(tmp); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		CGObjectInstance::readOwner(json); | ||||
| 		serializeJsonOwner(handler); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| std::string CGResource::getHoverText(PlayerColor player) const | ||||
| { | ||||
| 	return VLC->generaltexth->restypes[subID]; | ||||
| @@ -939,18 +933,11 @@ void CGResource::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) | ||||
| 		cb->startBattleI(hero, this); | ||||
| } | ||||
|  | ||||
| void CGResource::writeJsonOptions(JsonNode& json) const | ||||
| void CGResource::serializeJsonOptions(JsonSerializeFormat & handler) | ||||
| { | ||||
| 	CCreatureSet::writeJson(json["guards"]); | ||||
| 	json["amount"].Float() = amount; | ||||
| 	json["guardMessage"].String() = message; | ||||
| } | ||||
|  | ||||
| void CGResource::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	CCreatureSet::readJson(json["guards"]); | ||||
| 	amount = json["amount"].Float(); | ||||
| 	message = json["guardMessage"].String(); | ||||
| 	CCreatureSet::serializeJson(handler, "guards"); | ||||
| 	handler.serializeNumeric("amount", amount); | ||||
| 	handler.serializeString("guardMessage", message); | ||||
| } | ||||
|  | ||||
| CGTeleport::CGTeleport() : | ||||
| @@ -1439,25 +1426,21 @@ void CGArtifact::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) | ||||
| 		cb->startBattleI(hero, this); | ||||
| } | ||||
|  | ||||
| void CGArtifact::writeJsonOptions(JsonNode& json) const | ||||
| void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler) | ||||
| { | ||||
| 	CCreatureSet::writeJson(json["guards"]); | ||||
| 	json["guardMessage"].String() = message; | ||||
| 	if(ID == Obj::SPELL_SCROLL) | ||||
| 	handler.serializeString("guardMessage", message); | ||||
| 	CCreatureSet::serializeJson(handler, "guards"); | ||||
|  | ||||
| 	if(handler.saving && ID == Obj::SPELL_SCROLL) | ||||
| 	{ | ||||
| 		const Bonus * b = storedArtifact->getBonusLocalFirst(Selector::type(Bonus::SPELL)); | ||||
| 		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() | ||||
| { | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| 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 | ||||
| { | ||||
| 	int message; | ||||
| @@ -1665,23 +1642,9 @@ std::string CGShrine::getHoverText(const CGHeroInstance * hero) const | ||||
| 	return hoverName; | ||||
| } | ||||
|  | ||||
| void CGShrine::writeJsonOptions(JsonNode& json) const | ||||
| void CGShrine::serializeJsonOptions(JsonSerializeFormat& handler) | ||||
| { | ||||
| 	if(spell != SpellID::NONE) | ||||
| 	{ | ||||
| 		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()); | ||||
| 	} | ||||
| 	handler.serializeId("spell", &CSpellHandler::decodeSpell, &CSpellHandler::encodeSpell, SpellID(SpellID::NONE), spell); | ||||
| } | ||||
|  | ||||
| void CGSignBottle::initObj() | ||||
| @@ -1710,14 +1673,9 @@ void CGSignBottle::onHeroVisit( const CGHeroInstance * h ) const | ||||
| 		cb->removeObject(this); | ||||
| } | ||||
|  | ||||
| void CGSignBottle::writeJsonOptions(JsonNode& json) const | ||||
| void CGSignBottle::serializeJsonOptions(JsonSerializeFormat& handler) | ||||
| { | ||||
| 	json["text"].String() = message; | ||||
| } | ||||
|  | ||||
| void CGSignBottle::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	message = json["text"].String(); | ||||
| 	handler.serializeString("text", message); | ||||
| } | ||||
|  | ||||
| void CGScholar::onHeroVisit( const CGHeroInstance * h ) const | ||||
| @@ -1793,52 +1751,55 @@ void CGScholar::initObj() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGScholar::writeJsonOptions(JsonNode& json) const | ||||
| void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler) | ||||
| { | ||||
| 	switch(bonusType) | ||||
| 	JsonNode& json = handler.getCurrent(); | ||||
| 	if(handler.saving) | ||||
| 	{ | ||||
| 	case PRIM_SKILL: | ||||
| 		json["rewardPrimSkill"].String() = PrimarySkill::names[bonusID]; | ||||
| 		break; | ||||
| 	case SECONDARY_SKILL: | ||||
| 		json["rewardSkill"].String() = NSecondarySkill::names[bonusID]; | ||||
| 		break; | ||||
| 	case SPELL: | ||||
| 		json["rewardSpell"].String() = VLC->spellh->objects.at(bonusID)->identifier; | ||||
| 		break; | ||||
| 	case RANDOM: | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGScholar::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	bonusType = RANDOM; | ||||
| 	if(json["rewardPrimSkill"].String() != "") | ||||
| 	{ | ||||
| 		auto raw = VLC->modh->identifiers.getIdentifier("core", "primSkill", json["rewardPrimSkill"].String()); | ||||
| 		if(raw) | ||||
| 		switch(bonusType) | ||||
| 		{ | ||||
| 			bonusType = PRIM_SKILL; | ||||
| 			bonusID = raw.get(); | ||||
| 		case PRIM_SKILL: | ||||
| 			json["rewardPrimSkill"].String() = PrimarySkill::names[bonusID]; | ||||
| 			break; | ||||
| 		case SECONDARY_SKILL: | ||||
| 			json["rewardSkill"].String() = NSecondarySkill::names[bonusID]; | ||||
| 			break; | ||||
| 		case SPELL: | ||||
| 			json["rewardSpell"].String() = VLC->spellh->objects.at(bonusID)->identifier; | ||||
| 			break; | ||||
| 		case RANDOM: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	else if(json["rewardSkill"].String() != "") | ||||
| 	else | ||||
| 	{ | ||||
| 		auto raw = VLC->modh->identifiers.getIdentifier("core", "skill", json["rewardSkill"].String()); | ||||
| 		if(raw) | ||||
| 		bonusType = RANDOM; | ||||
| 		if(json["rewardPrimSkill"].String() != "") | ||||
| 		{ | ||||
| 			bonusType = SECONDARY_SKILL; | ||||
| 			bonusID = raw.get(); | ||||
| 			auto raw = VLC->modh->identifiers.getIdentifier("core", "primSkill", json["rewardPrimSkill"].String()); | ||||
| 			if(raw) | ||||
| 			{ | ||||
| 				bonusType = PRIM_SKILL; | ||||
| 				bonusID = raw.get(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if(json["rewardSpell"].String() != "") | ||||
| 	{ | ||||
| 		auto raw = VLC->modh->identifiers.getIdentifier("core", "spell", json["rewardSpell"].String()); | ||||
| 		if(raw) | ||||
| 		else if(json["rewardSkill"].String() != "") | ||||
| 		{ | ||||
| 			bonusType = SPELL; | ||||
| 			bonusID = raw.get(); | ||||
| 			auto raw = VLC->modh->identifiers.getIdentifier("core", "skill", json["rewardSkill"].String()); | ||||
| 			if(raw) | ||||
| 			{ | ||||
| 				bonusType = SECONDARY_SKILL; | ||||
| 				bonusID = raw.get(); | ||||
| 			} | ||||
| 		} | ||||
| 		else if(json["rewardSpell"].String() != "") | ||||
| 		{ | ||||
| 			auto raw = VLC->modh->identifiers.getIdentifier("core", "spell", json["rewardSpell"].String()); | ||||
| 			if(raw) | ||||
| 			{ | ||||
| 				bonusType = SPELL; | ||||
| 				bonusID = raw.get(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1879,18 +1840,11 @@ void CGGarrison::battleFinished(const CGHeroInstance *hero, const BattleResult & | ||||
| 		onHeroVisit(hero); | ||||
| } | ||||
|  | ||||
| void CGGarrison::writeJsonOptions(JsonNode& json) const | ||||
| void CGGarrison::serializeJsonOptions(JsonSerializeFormat& handler) | ||||
| { | ||||
| 	CCreatureSet::writeJson(json["army"]); | ||||
| 	CGObjectInstance::writeOwner(json); | ||||
| 	json["removableUnits"].Bool() = removableUnits; | ||||
| } | ||||
|  | ||||
| void CGGarrison::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	CCreatureSet::readJson(json["army"]); | ||||
| 	CGObjectInstance::readOwner(json); | ||||
| 	removableUnits = json["removableUnits"].Bool(); | ||||
| 	handler.serializeBool("removableUnits", removableUnits); | ||||
| 	serializeJsonOwner(handler); | ||||
| 	CCreatureSet::serializeJson(handler, "army"); | ||||
| } | ||||
|  | ||||
| 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); | ||||
| } | ||||
|  | ||||
| void CGShipyard::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	CGObjectInstance::readOwner(json); | ||||
| 	serializeJsonOwner(handler); | ||||
| } | ||||
|  | ||||
| void CCartographer::onHeroVisit( const CGHeroInstance * h ) const | ||||
| @@ -2222,12 +2171,7 @@ void CGLighthouse::giveBonusTo( PlayerColor player ) const | ||||
| 	cb->sendAndApply(&gb); | ||||
| } | ||||
|  | ||||
| void CGLighthouse::writeJsonOptions(JsonNode& json) const | ||||
| void CGLighthouse::serializeJsonOptions(JsonSerializeFormat& handler) | ||||
| { | ||||
| 	CGObjectInstance::writeOwner(json); | ||||
| } | ||||
|  | ||||
| void CGLighthouse::readJsonOptions(const JsonNode& json) | ||||
| { | ||||
| 	CGObjectInstance::readOwner(json); | ||||
| 	serializeJsonOwner(handler); | ||||
| } | ||||
|   | ||||
| @@ -86,11 +86,9 @@ public: | ||||
| 	} | ||||
| protected: | ||||
| 	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: | ||||
|  | ||||
| 	void fight(const CGHeroInstance *h) const; | ||||
| 	void flee( const CGHeroInstance * h ) const; | ||||
| 	void fleeDecision(const CGHeroInstance *h, ui32 pursue) const; | ||||
| @@ -101,7 +99,6 @@ private: | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles | ||||
| { | ||||
| public: | ||||
| @@ -116,8 +113,7 @@ public: | ||||
| 		h & message; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGWitchHut : public CPlayersVisited | ||||
| @@ -136,8 +132,7 @@ public: | ||||
| 		h & allowedAbilities & ability; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGScholar : public CGObjectInstance | ||||
| @@ -156,8 +151,7 @@ public: | ||||
| 		h & bonusType & bonusID; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGGarrison : public CArmedInstance | ||||
| @@ -175,8 +169,7 @@ public: | ||||
| 		h & removableUnits; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGArtifact : public CArmedInstance | ||||
| @@ -202,8 +195,7 @@ public: | ||||
| 		h & message & storedArtifact; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGResource : public CArmedInstance | ||||
| @@ -227,8 +219,7 @@ public: | ||||
| 		h & amount & message; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGShrine : public CPlayersVisited | ||||
| @@ -246,8 +237,7 @@ public: | ||||
| 		h & spell; | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGMine : public CArmedInstance | ||||
| @@ -277,8 +267,7 @@ public: | ||||
| 	} | ||||
| 	ui32 defaultResProduction(); | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| struct DLL_LINKAGE TeleportChannel | ||||
| @@ -444,8 +433,7 @@ public: | ||||
| 		h & static_cast<IShipyard&>(*this); | ||||
| 	} | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGMagi : public CGObjectInstance | ||||
| @@ -462,8 +450,6 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| class DLL_LINKAGE CCartographer : public CPlayersVisited | ||||
| { | ||||
| ///behaviour varies depending on surface and  floor | ||||
| @@ -515,6 +501,5 @@ public: | ||||
| 	} | ||||
| 	void giveBonusTo( PlayerColor player ) const; | ||||
| protected: | ||||
| 	void writeJsonOptions(JsonNode & json) const override; | ||||
| 	void readJsonOptions(const JsonNode & json) override; | ||||
| 	void serializeJsonOptions(JsonSerializeFormat & handler) override; | ||||
| }; | ||||
|   | ||||
| @@ -525,7 +525,7 @@ std::unique_ptr<CMapHeader> CMapLoaderJson::loadMapHeader() | ||||
| 	return std::move(result); | ||||
| } | ||||
|  | ||||
| const JsonNode CMapLoaderJson::getFromArchive(const std::string & archiveFilename) | ||||
| JsonNode CMapLoaderJson::getFromArchive(const std::string & archiveFilename) | ||||
| { | ||||
| 	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, '_')) | ||||
| { | ||||
|  | ||||
| @@ -797,7 +797,9 @@ void CMapLoaderJson::MapObjectLoader::configure() | ||||
| 	if(nullptr == instance) | ||||
| 		return; | ||||
|  | ||||
| 	instance->readJson(configuration); | ||||
| 	JsonDeserializer handler(configuration); | ||||
|  | ||||
| 	instance->serializeJson(handler); | ||||
|  | ||||
| 	if(instance->ID == Obj::TOWN) | ||||
| 	{ | ||||
| @@ -841,10 +843,10 @@ void CMapLoaderJson::readObjects() | ||||
|  | ||||
| 	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 | ||||
| 	for(const auto & p : data.Struct()) | ||||
| 	for(auto & p : data.Struct()) | ||||
| 		loaders.push_back(vstd::make_unique<MapObjectLoader>(this, p)); | ||||
|  | ||||
| 	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); | ||||
|  | ||||
| 	for(const CGObjectInstance * obj : map->objects) | ||||
| 		obj->writeJson(data[obj->getStringId()]); | ||||
| 	JsonSerializer handler(data); | ||||
|  | ||||
| 	for(CGObjectInstance * obj : map->objects) | ||||
| 	{ | ||||
| 		auto temp = handler.enterStruct(obj->getStringId()); | ||||
|  | ||||
| 		obj->serializeJson(handler); | ||||
| 	} | ||||
|  | ||||
| 	if(map->grailPos.valid()) | ||||
| 	{ | ||||
| @@ -1010,7 +1018,6 @@ void CMapSaverJson::writeObjects() | ||||
| 		std::string grailId = boost::str(boost::format("grail_%d") % map->objects.size()); | ||||
|  | ||||
| 		data[grailId] = grail; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	addToArchive(data, OBJECTS_FILE_NAME); | ||||
|   | ||||
| @@ -159,12 +159,12 @@ private: | ||||
|  | ||||
| 	struct MapObjectLoader | ||||
| 	{ | ||||
| 		MapObjectLoader(CMapLoaderJson * _owner, const JsonMap::value_type & json); | ||||
| 		MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type & json); | ||||
| 		CMapLoaderJson * owner; | ||||
| 		CGObjectInstance * instance; | ||||
| 		ObjectInstanceID id; | ||||
| 		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) | ||||
| 		///constructs object (without configuration) | ||||
| 		void construct(); | ||||
| @@ -197,7 +197,7 @@ private: | ||||
| 	 */ | ||||
| 	void readObjects(); | ||||
|  | ||||
| 	const JsonNode getFromArchive(const std::string & archiveFilename); | ||||
| 	JsonNode getFromArchive(const std::string & archiveFilename); | ||||
|  | ||||
| 	CInputStream * buffer; | ||||
| 	std::shared_ptr<CIOApi> ioApi; | ||||
|   | ||||
| @@ -48,6 +48,24 @@ void JsonDeserializer::serializeIntEnum(const std::string & fieldName, const std | ||||
| 		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) | ||||
| { | ||||
| 	const JsonNode & field = current->operator[](fieldName); | ||||
|   | ||||
| @@ -27,4 +27,5 @@ public: | ||||
| protected: | ||||
| 	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 serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) override; | ||||
| }; | ||||
|   | ||||
| @@ -98,6 +98,16 @@ public: | ||||
|  | ||||
| 	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: | ||||
| 	JsonNode * root; | ||||
| 	JsonNode * current; | ||||
| @@ -107,6 +117,8 @@ protected: | ||||
| 	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 serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) = 0; | ||||
| private: | ||||
| 	friend class JsonStructSerializer; | ||||
| }; | ||||
|   | ||||
| @@ -40,6 +40,15 @@ void JsonSerializer::serializeIntEnum(const std::string & fieldName, const std:: | ||||
| 	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) | ||||
| { | ||||
| 	assert(standard.size() == value.size()); | ||||
|   | ||||
| @@ -27,4 +27,5 @@ public: | ||||
| protected: | ||||
| 	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 serializeIntId(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const si32 defaultValue, si32 & value) override; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user