瀏覽代碼

Serialize template

nordsoft 2 年之前
父節點
當前提交
53b2f68560

+ 99 - 25
client/lobby/RandomMapTab.cpp

@@ -47,21 +47,15 @@ RandomMapTab::RandomMapTab():
 	addCallback("toggleTwoLevels", [&](bool on)
 	{
 		mapGenOptions->setHasTwoLevels(on);
+		setTemplate(mapGenOptions->getMapTemplate());
 		updateMapInfoByHost();
 	});
 	
 	addCallback("setPlayersCount", [&](int btnId)
 	{
 		mapGenOptions->setPlayerCount(btnId);
-	
-		if(auto w = widget<CToggleGroup>("groupMaxTeams"))
-			deactivateButtonsFrom(w.get(), btnId);
-
-		// deactive some CompOnlyPlayers buttons to prevent total number of players exceeds PlayerColor::PLAYER_LIMIT_I
-		if(auto w = widget<CToggleGroup>("groupCompOnlyPlayers"))
-			deactivateButtonsFrom(w.get(), PlayerColor::PLAYER_LIMIT_I - btnId + 1);
-
-		validatePlayersCnt(btnId);
+		setMapGenOptions(mapGenOptions);
+		//validatePlayersCnt(btnId);
 		updateMapInfoByHost();
 	});
 	
@@ -74,14 +68,8 @@ RandomMapTab::RandomMapTab():
 	addCallback("setCompOnlyPlayers", [&](int btnId)
 	{
 		mapGenOptions->setCompOnlyPlayerCount(btnId);
-
-		// deactive some MaxPlayers buttons to prevent total number of players exceeds PlayerColor::PLAYER_LIMIT_I
-		if(auto w = widget<CToggleGroup>("groupMaxPlayers"))
-			deactivateButtonsFrom(w.get(), PlayerColor::PLAYER_LIMIT_I - btnId + 1);
-		
-		if(auto w = widget<CToggleGroup>("groupCompOnlyTeams"))
-			deactivateButtonsFrom(w.get(), (btnId == 0 ? 1 : btnId));
-		validateCompOnlyPlayersCnt(btnId);
+		setMapGenOptions(mapGenOptions);
+		//validateCompOnlyPlayersCnt(btnId);
 		updateMapInfoByHost();
 	});
 	
@@ -173,20 +161,80 @@ void RandomMapTab::updateMapInfoByHost()
 
 void RandomMapTab::setMapGenOptions(std::shared_ptr<CMapGenOptions> opts)
 {
+	mapGenOptions = opts;
+	
+	//prepare allowed options
+	for(int i = 0; i <= PlayerColor::PLAYER_LIMIT_I; ++i)
+	{
+		playerCountAllowed.insert(i);
+		compCountAllowed.insert(i);
+		playerTeamsAllowed.insert(i);
+		compTeamsAllowed.insert(i);
+	}
+	auto * tmpl = mapGenOptions->getMapTemplate();
+	if(tmpl)
+	{
+		playerCountAllowed = tmpl->getPlayers().getNumbers();
+		compCountAllowed = tmpl->getCpuPlayers().getNumbers();
+	}
+	if(mapGenOptions->getPlayerCount() != CMapGenOptions::RANDOM_SIZE)
+	{
+		vstd::erase_if(compCountAllowed,
+		[opts](int el){
+			return PlayerColor::PLAYER_LIMIT_I - opts->getPlayerCount() < el;
+		});
+		vstd::erase_if(playerTeamsAllowed,
+		[opts](int el){
+			return PlayerColor::PLAYER_LIMIT_I - opts->getPlayerCount() < el + 1;
+		});
+	}
+	if(mapGenOptions->getCompOnlyPlayerCount() != CMapGenOptions::RANDOM_SIZE)
+	{
+		vstd::erase_if(playerCountAllowed,
+		[opts](int el){
+			return PlayerColor::PLAYER_LIMIT_I - opts->getCompOnlyPlayerCount() < el;
+		});
+		vstd::erase_if(compTeamsAllowed,
+		[opts](int el){
+			return PlayerColor::PLAYER_LIMIT_I - opts->getCompOnlyPlayerCount() < el + 1;
+		});
+	}
+	
 	if(auto w = widget<CToggleGroup>("groupMapSize"))
 		w->setSelected(vstd::find_pos(getPossibleMapSizes(), opts->getWidth()));
 	if(auto w = widget<CToggleButton>("buttonTwoLevels"))
 		w->setSelected(opts->getHasTwoLevels());
 	if(auto w = widget<CToggleGroup>("groupMaxPlayers"))
+	{
 		w->setSelected(opts->getPlayerCount());
+		deactivateButtonsFrom(*w, playerCountAllowed);
+	}
 	if(auto w = widget<CToggleGroup>("groupMaxTeams"))
+	{
 		w->setSelected(opts->getTeamCount());
+		deactivateButtonsFrom(*w, playerCountAllowed);
+	}
 	if(auto w = widget<CToggleGroup>("groupCompOnlyPlayers"))
+	{
 		w->setSelected(opts->getCompOnlyPlayerCount());
+		deactivateButtonsFrom(*w, playerTeamsAllowed);
+	}
 	if(auto w = widget<CToggleGroup>("groupCompOnlyTeams"))
+	{
 		w->setSelected(opts->getCompOnlyTeamCount());
+		deactivateButtonsFrom(*w, compTeamsAllowed);
+	}
 	if(auto w = widget<CToggleGroup>("groupWaterContent"))
+	{
 		w->setSelected(opts->getWaterContent());
+		if(opts->getMapTemplate())
+		{
+			std::set<int> allowedWater(opts->getMapTemplate()->getWaterContentAllowed().begin(), opts->getMapTemplate()->getWaterContentAllowed().end());
+			deactivateButtonsFrom(*w, allowedWater);
+		}
+		else
+			deactivateButtonsFrom(*w, {-1});
+	}
 	if(auto w = widget<CToggleGroup>("groupMonsterStrength"))
 		w->setSelected(opts->getMonsterStrength());
 }
@@ -194,6 +242,7 @@ void RandomMapTab::setMapGenOptions(std::shared_ptr<CMapGenOptions> opts)
 void RandomMapTab::setTemplate(const CRmgTemplate * tmpl)
 {
 	mapGenOptions->setMapTemplate(tmpl);
+	setMapGenOptions(mapGenOptions);
 	if(auto w = widget<CButton>("templateButton"))
 	{
 		if(tmpl)
@@ -201,16 +250,41 @@ void RandomMapTab::setTemplate(const CRmgTemplate * tmpl)
 		else
 			w->addTextOverlay("default", EFonts::FONT_SMALL);
 	}
+	updateMapInfoByHost();
+}
+
+void RandomMapTab::deactivateButtonsFrom(CToggleGroup & group, int startAllowed, int endAllowed)
+{
+	logGlobal->debug("Blocking all buttons except %d - %d", startAllowed, endAllowed);
+	for(auto toggle : group.buttons)
+	{
+		if(auto button = std::dynamic_pointer_cast<CToggleButton>(toggle.second))
+		{
+			if(toggle.first == CMapGenOptions::RANDOM_SIZE
+			   || (startAllowed == CMapGenOptions::RANDOM_SIZE && endAllowed == CMapGenOptions::RANDOM_SIZE)
+			   || (toggle.first >= startAllowed
+			   && (endAllowed == CMapGenOptions::RANDOM_SIZE || toggle.first <= endAllowed)))
+			{
+				//button->block(false);
+			}
+			else
+			{
+				button->block(true);
+			}
+		}
+	}
 }
 
-void RandomMapTab::deactivateButtonsFrom(CToggleGroup * group, int startId)
+void RandomMapTab::deactivateButtonsFrom(CToggleGroup & group, const std::set<int> & allowed)
 {
-	logGlobal->debug("Blocking buttons from %d", startId);
-	for(auto toggle : group->buttons)
+	logGlobal->debug("Blocking buttons");
+	for(auto toggle : group.buttons)
 	{
 		if(auto button = std::dynamic_pointer_cast<CToggleButton>(toggle.second))
 		{
-			if(startId == CMapGenOptions::RANDOM_SIZE || toggle.first < startId)
+			if(allowed.count(CMapGenOptions::RANDOM_SIZE)
+			   || allowed.count(toggle.first)
+			   || toggle.first == CMapGenOptions::RANDOM_SIZE)
 			{
 				button->block(false);
 			}
@@ -229,7 +303,7 @@ void RandomMapTab::validatePlayersCnt(int playersCnt)
 		return;
 	}
 
-	if(mapGenOptions->getTeamCount() >= playersCnt)
+	/*if(mapGenOptions->getTeamCount() >= playersCnt)
 	{
 		mapGenOptions->setTeamCount(playersCnt - 1);
 		if(auto w = widget<CToggleGroup>("groupMaxTeams"))
@@ -241,7 +315,7 @@ void RandomMapTab::validatePlayersCnt(int playersCnt)
 		mapGenOptions->setCompOnlyPlayerCount(PlayerColor::PLAYER_LIMIT_I - playersCnt);
 		if(auto w = widget<CToggleGroup>("groupCompOnlyPlayers"))
 			w->setSelected(mapGenOptions->getCompOnlyPlayerCount());
-	}
+	}*/
 
 	validateCompOnlyPlayersCnt(mapGenOptions->getCompOnlyPlayerCount());
 }
@@ -253,14 +327,14 @@ void RandomMapTab::validateCompOnlyPlayersCnt(int compOnlyPlayersCnt)
 		return;
 	}
 
-	if(mapGenOptions->getCompOnlyTeamCount() >= compOnlyPlayersCnt)
+	/*if(mapGenOptions->getCompOnlyTeamCount() >= compOnlyPlayersCnt)
 	{
 		int compOnlyTeamCount = compOnlyPlayersCnt == 0 ? 0 : compOnlyPlayersCnt - 1;
 		mapGenOptions->setCompOnlyTeamCount(compOnlyTeamCount);
 		updateMapInfoByHost();
 		if(auto w = widget<CToggleGroup>("groupCompOnlyTeams"))
 			w->setSelected(compOnlyTeamCount);
-	}
+	}*/
 }
 
 std::vector<int> RandomMapTab::getPossibleMapSizes()

+ 5 - 1
client/lobby/RandomMapTab.h

@@ -39,13 +39,17 @@ public:
 	CFunctionList<void(std::shared_ptr<CMapInfo>, std::shared_ptr<CMapGenOptions>)> mapInfoChanged;
 
 private:
-	void deactivateButtonsFrom(CToggleGroup * group, int startId);
+	void deactivateButtonsFrom(CToggleGroup & group, int startAllower, int endAllowed);
+	void deactivateButtonsFrom(CToggleGroup & group, const std::set<int> & allowed);
 	void validatePlayersCnt(int playersCnt);
 	void validateCompOnlyPlayersCnt(int compOnlyPlayersCnt);
 	std::vector<int> getPossibleMapSizes();
 
 	std::shared_ptr<CMapGenOptions> mapGenOptions;
 	std::shared_ptr<CMapInfo> mapInfo;
+	
+	//options allowed - need to store as impact each other
+	std::set<int> playerCountAllowed, playerTeamsAllowed, compCountAllowed, compTeamsAllowed;
 };
 
 class TemplatesDropBox : public CIntObject

+ 24 - 2
lib/rmg/CMapGenOptions.cpp

@@ -204,8 +204,30 @@ const CRmgTemplate * CMapGenOptions::getMapTemplate() const
 void CMapGenOptions::setMapTemplate(const CRmgTemplate * value)
 {
 	mapTemplate = value;
-	//TODO validate & adapt options according to template
-	//assert(0);
+	//validate & adapt options according to template
+	if(mapTemplate)
+	{
+		if(!mapTemplate->matchesSize(int3(getWidth(), getHeight(), 1 + getHasTwoLevels())))
+		{
+			auto sizes = mapTemplate->getMapSizes();
+			setWidth(sizes.first.x);
+			setHeight(sizes.first.y);
+			setHasTwoLevels(sizes.first.z - 1);
+		}
+		
+		if(!mapTemplate->getPlayers().isInRange(getPlayerCount()))
+			setPlayerCount(RANDOM_SIZE);
+		if(!mapTemplate->getCpuPlayers().isInRange(getCompOnlyPlayerCount()))
+			setCompOnlyPlayerCount(RANDOM_SIZE);
+		if(!mapTemplate->getWaterContentAllowed().count(getWaterContent()))
+			setWaterContent(EWaterContent::RANDOM);
+	}
+}
+
+void CMapGenOptions::setMapTemplate(const std::string & name)
+{
+	if(!name.empty())
+		setMapTemplate(VLC->tplh->getTemplate(name));
 }
 
 void CMapGenOptions::finalize(CRandomGenerator & rand)

+ 13 - 27
lib/rmg/CMapGenOptions.h

@@ -11,37 +11,12 @@
 #pragma once
 
 #include "../GameConstants.h"
+#include "CRmgTemplate.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class CRmgTemplate;
 class CRandomGenerator;
 
-namespace EWaterContent
-{
-	enum EWaterContent
-	{
-		RANDOM = -1,
-		NONE,
-		NORMAL,
-		ISLANDS
-	};
-}
-
-namespace EMonsterStrength
-{
-	enum EMonsterStrength
-	{
-		RANDOM = -2,
-		ZONE_WEAK = -1,
-		ZONE_NORMAL = 0,
-		ZONE_STRONG = 1,
-		GLOBAL_WEAK = 2,
-		GLOBAL_NORMAL = 3,
-		GLOBAL_STRONG = 4
-	};
-}
-
 namespace EPlayerType
 {
 	enum EPlayerType
@@ -143,6 +118,7 @@ public:
 	/// Default: Not set/random.
 	const CRmgTemplate * getMapTemplate() const;
 	void setMapTemplate(const CRmgTemplate * value);
+	void setMapTemplate(const std::string & name);
 
 	std::vector<const CRmgTemplate *> getPossibleTemplates() const;
 
@@ -187,7 +163,17 @@ public:
 		h & waterContent;
 		h & monsterStrength;
 		h & players;
-		//TODO add name of template to class, enables selection of a template by a user
+		std::string templateName;
+		if(mapTemplate && h.saving)
+		{
+			templateName = mapTemplate->getId();
+		}
+		//if(version > xxx) do not forget to bump version
+		h & templateName;
+		if(!h.saving)
+		{
+			setMapTemplate(templateName);
+		}
 	}
 };
 

+ 16 - 1
lib/rmg/CRmgTemplate.cpp

@@ -501,9 +501,19 @@ void CRmgTemplate::setId(const std::string & value)
 	id = value;
 }
 
+void CRmgTemplate::setName(const std::string & value)
+{
+	name = value;
+}
+
 const std::string & CRmgTemplate::getName() const
 {
-	return name.empty() ? id : name;
+	return name;
+}
+
+const std::string & CRmgTemplate::getId() const
+{
+	return id;
 }
 
 const CRmgTemplate::CPlayerCountRange & CRmgTemplate::getPlayers() const
@@ -531,6 +541,11 @@ void CRmgTemplate::validate() const
 	//TODO add some validation checks, throw on failure
 }
 
+std::pair<int3, int3> CRmgTemplate::getMapSizes() const
+{
+	return {minSize, maxSize};
+}
+
 void CRmgTemplate::CPlayerCountRange::addRange(int lower, int upper)
 {
 	range.push_back(std::make_pair(lower, upper));

+ 28 - 1
lib/rmg/CRmgTemplate.h

@@ -14,7 +14,6 @@
 #include "../GameConstants.h"
 #include "../ResourceSet.h"
 #include "../Terrain.h"
-#include "CMapGenOptions.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -32,6 +31,31 @@ namespace ETemplateZoneType
 	};
 }
 
+namespace EWaterContent
+{
+	enum EWaterContent
+	{
+		RANDOM = -1,
+		NONE,
+		NORMAL,
+		ISLANDS
+	};
+}
+
+namespace EMonsterStrength
+{
+	enum EMonsterStrength
+	{
+		RANDOM = -2,
+		ZONE_WEAK = -1,
+		ZONE_NORMAL = 0,
+		ZONE_STRONG = 1,
+		GLOBAL_WEAK = 2,
+		GLOBAL_NORMAL = 3,
+		GLOBAL_STRONG = 4
+	};
+}
+
 class DLL_LINKAGE CTreasureInfo
 {
 public:
@@ -194,10 +218,13 @@ public:
 	const std::set<EWaterContent::EWaterContent> & getWaterContentAllowed() const;
 
 	void setId(const std::string & value);
+	void setName(const std::string & value);
+	const std::string & getId() const;
 	const std::string & getName() const;
 
 	const CPlayerCountRange & getPlayers() const;
 	const CPlayerCountRange & getCpuPlayers() const;
+	std::pair<int3, int3> getMapSizes() const;
 	const Zones & getZones() const;
 	const std::vector<rmg::ZoneConnection> & getConnections() const;
 

+ 2 - 1
lib/rmg/CRmgTemplateStorage.cpp

@@ -31,8 +31,9 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
 	{
 		JsonDeserializer handler(nullptr, data);
 		auto fullKey = normalizeIdentifier(scope, "core", name); //actually it's not used
-		templates[fullKey].setId(name);
+		templates[fullKey].setId(fullKey);
 		templates[fullKey].serializeJson(handler);
+		templates[fullKey].setName(name);
 		templates[fullKey].validate();
 	}
 	catch(const std::exception & e)

+ 1 - 0
lib/rmg/CZonePlacer.cpp

@@ -13,6 +13,7 @@
 #include "CZonePlacer.h"
 #include "../mapping/CMap.h"
 #include "../mapping/CMapEditManager.h"
+#include "CMapGenOptions.h"
 #include "RmgMap.h"
 #include "Zone.h"
 #include "Functions.h"

+ 1 - 0
lib/rmg/Functions.h

@@ -19,6 +19,7 @@ class RmgMap;
 class ObjectManager;
 class ObjectTemplate;
 class CMapGenerator;
+class CRandomGenerator;
 
 class rmgException : public std::exception
 {