2
0
Эх сурвалжийг харах

Initial implementation of new team settings format

AlexVinS 10 жил өмнө
parent
commit
8493d0cded

+ 1 - 1
lib/mapping/CMapService.h

@@ -145,6 +145,6 @@ public:
 	/**
 	 * Saves the VCMI/H3 map file.
 	 *
-	 */	
+	 */
 	 virtual void saveMap(const std::unique_ptr<CMap> & map) = 0;
 };

+ 107 - 28
lib/mapping/MapFormatJson.cpp

@@ -109,6 +109,14 @@ namespace TerrainDetail
 	};
 }
 
+namespace MapHeaderDetail
+{
+	static const std::array<std::string, PlayerColor::PLAYER_LIMIT_I>  playerColorNames =
+	{
+		"red", "blue", "tan", "green", "orange", "purple", "teal", "pink"
+	};
+}
+
 ///CMapFormatJson
 const int CMapFormatJson::VERSION_MAJOR = 1;
 const int CMapFormatJson::VERSION_MINOR = 0;
@@ -213,7 +221,7 @@ CMapLoaderJson::CMapLoaderJson(CInputOutputStream * stream):
 si32 CMapLoaderJson::getIdentifier(const std::string& type, const std::string& name)
 {
 	boost::optional<si32> res = VLC->modh->identifiers.getIdentifier("core", type, name, false);
-	
+
 	if(!res)
 	{
 		throw new std::runtime_error("Map load failed. Identifier not resolved.");
@@ -297,6 +305,7 @@ void CMapLoaderJson::readHeader()
 
 	readTriggeredEvents(header);
 	readPlayerInfo(header);
+	readTeams(header);
 	//TODO: readHeader
 }
 
@@ -319,7 +328,6 @@ void CMapLoaderJson::readPlayerInfo(const JsonNode & input)
 		else
 		{
 			readPlayerInfo(info, playerSrc);
-			vstd::amax(howManyTeams, info.team.getNum()+1);
 		}
 	}
 	mapHeader->howManyTeams = howManyTeams;
@@ -328,28 +336,63 @@ void CMapLoaderJson::readPlayerInfo(const JsonNode & input)
 void CMapLoaderJson::readPlayerInfo(PlayerInfo& info, const JsonNode& input)
 {
 	//allowed factions
-	
+
 	info.isFactionRandom = input["randomFaction"].Bool();
-	info.canComputerPlay = input["canComputerPlay"].Bool();	
+	info.canComputerPlay = input["canComputerPlay"].Bool();
 	info.canHumanPlay = input["canHumanPlay"].Bool();
-	
-	//plasedHeroes
-	
+
+	//placedHeroes
+
 	//mainTown
-	
+
 	info.generateHeroAtMainTown = input["generateHeroAtMainTown"].Bool();
-	
+
 	info.hasRandomHero = input["randomHero"].Bool();
-	
+
 	//mainHero
-	
+
 	//mainHeroPortrait
-	
+
 	info.mainCustomHeroName = input["mainHeroName"].String();
-	
-	info.team = TeamID(input["team"].Float());
 }
 
+void CMapLoaderJson::readTeams(const JsonNode& input)
+{
+	const JsonNode & src = input["teams"];
+
+    if(src.getType() != JsonNode::DATA_VECTOR)
+	{
+		// No alliances
+		if(src.getType() != JsonNode::DATA_NULL)
+			logGlobal->errorStream() << "Invalid teams field type";
+
+		mapHeader->howManyTeams = 0;
+		for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
+		{
+			if(mapHeader->players[i].canComputerPlay || mapHeader->players[i].canHumanPlay)
+			{
+				mapHeader->players[i].team = TeamID(mapHeader->howManyTeams++);
+			}
+		}
+	}
+	else
+	{
+		const JsonVector & srcVector = src.Vector();
+		mapHeader->howManyTeams = srcVector.size();
+
+		for(int team = 0; team < mapHeader->howManyTeams; team++)
+		{
+			for(const JsonNode & playerData : srcVector[team].Vector())
+			{
+				PlayerColor player = PlayerColor(vstd::find_pos(MapHeaderDetail::playerColorNames, playerData.String()));
+				if(player.isValidPlayer())
+				{
+					map->players[player.getNum()].team = TeamID(team);
+				}
+			}
+		}
+	}
+}
 
 void CMapLoaderJson::readTerrainTile(const std::string& src, TerrainTile& tile)
 {
@@ -476,7 +519,6 @@ void CMapLoaderJson::readTerrainLevel(const JsonNode& src, const int index)
 	}
 }
 
-
 void CMapLoaderJson::readTerrain()
 {
 	{
@@ -567,6 +609,8 @@ void CMapSaverJson::writeHeader()
 
 	writePlayerInfo(header);
 
+	writeTeams(header);
+
 	//todo:	allowedHeroes;
 	//todo: placeholdedHeroes;
 
@@ -577,11 +621,11 @@ void CMapSaverJson::writePlayerInfo(JsonNode & output)
 {
 	JsonNode & dest = output["players"];
 	dest.setType(JsonNode::DATA_STRUCT);
-	
+
 	for(int player = 0; player < PlayerColor::PLAYER_LIMIT_I; player++)
 	{
 		const PlayerInfo & info = map->players[player];
-		
+
 		if(info.canAnyonePlay())
 			writePlayerInfo(info, dest[GameConstants::PLAYER_COLOR_NAMES[player]]);
 	}
@@ -590,27 +634,62 @@ void CMapSaverJson::writePlayerInfo(JsonNode & output)
 void CMapSaverJson::writePlayerInfo(const PlayerInfo & info, JsonNode & output)
 {
 	//allowed factions
-	
+
 	output["randomFaction"].Bool() = info.isFactionRandom;
-	
+
 	output["canComputerPlay"].Bool() = info.canComputerPlay;
 	output["canHumanPlay"].Bool() = info.canHumanPlay;
-	
+
 	//plasedHeroes
-	
+
 	//mainTown
-	
+
 	output["generateHeroAtMainTown"].Bool() = info.generateHeroAtMainTown;
-	
+
 	output["randomHero"].Bool() = info.hasRandomHero;
-	
+
 	//mainHero
-	
+
 	//mainHeroPortrait
-	
+
 	output["mainHeroName"].String() =  info.mainCustomHeroName;
-	
-	output["team"].Float() = info.team.getNum();	
+}
+
+void CMapSaverJson::writeTeams(JsonNode& output)
+{
+	JsonNode & dest = output["teams"];
+	std::vector<std::set<PlayerColor>> teamsData;
+
+	teamsData.resize(map->howManyTeams);
+
+	//get raw data
+	for(int idx = 0; idx < map->players.size(); idx++)
+	{
+		const PlayerInfo & player = map->players.at(idx);
+		int team = player.team.getNum();
+		if(vstd::isbetween(team, 0, map->howManyTeams-1))
+			teamsData.at(team).insert(PlayerColor(idx));
+	}
+
+	//remove single-member teams
+	vstd::erase_if(teamsData, [](std::set<PlayerColor> & elem) -> bool
+	{
+		return elem.size() <= 1;
+	});
+
+	dest.setType(JsonNode::DATA_VECTOR);
+
+	for(const std::set<PlayerColor> & teamData : teamsData)
+	{
+		JsonNode team(JsonNode::DATA_VECTOR);
+		for(const PlayerColor & player : teamData)
+		{
+			JsonNode member(JsonNode::DATA_STRING);
+			member.String() = GameConstants::PLAYER_COLOR_NAMES[player.getNum()];
+			team.Vector().push_back(std::move(member));
+		}
+		dest.Vector().push_back(std::move(team));
+	}
 }
 
 const std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile)

+ 5 - 1
lib/mapping/MapFormatJson.h

@@ -143,6 +143,8 @@ private:
 	 */
 	void readPlayerInfo(PlayerInfo & info, const JsonNode & input);
 	
+	void readTeams(const JsonNode & input);
+	
 	void readTerrainTile(const std::string & src, TerrainTile & tile);
 	
 	void readTerrainLevel(const JsonNode & src, const int index);	
@@ -189,7 +191,9 @@ private:
 	 * Save one player info
 	 * @param output empty object	 
 	 */	
-	void writePlayerInfo(const PlayerInfo & info, JsonNode & output);	
+	void writePlayerInfo(const PlayerInfo & info, JsonNode & output);
+	
+	void writeTeams(JsonNode & output);	
 
 	const std::string writeTerrainTile(const TerrainTile & tile);