Răsfoiți Sursa

Merge branch 'develop' into battleonly

Laserlicht 1 lună în urmă
părinte
comite
743013a0d6

+ 1 - 1
client/windows/GUIClasses.cpp

@@ -1678,7 +1678,7 @@ void CObjectListWindow::trimTextIfTooWide(std::string & text, bool preserveCount
 	{
 		auto posBrace = text.find_last_of("(");
 		auto posClosing = text.find_last_of(")");
-		if (posBrace != std::string::npos && posClosing != std::string::npos && posBrace < posClosing)
+		if (posBrace != std::string::npos && posClosing != std::string::npos && posClosing > posBrace)
 		{
 			std::string objCount = text.substr(posBrace, posClosing - posBrace) + ')';
 			suffix += " ";

+ 1 - 1
launcher/lib/innoextract

@@ -1 +1 @@
-Subproject commit 98bb55798a77c0346b12a1dbb53fe4d3e0379d66
+Subproject commit 96e9566a35fb51ebf13ffbdadfd49a93c1ae5c1a

+ 8 - 4
launcher/modManager/cmodlistview_moc.cpp

@@ -1110,8 +1110,10 @@ void CModListView::installMaps(QStringList maps)
 		}
 		else
 		{
-			QString fileName = map.section('/', -1, -1);
-			if (QFile::exists(destDir + fileName))
+		    QString srcPath = Helper::getRealPath(map);
+		    QString fileName = QFileInfo(srcPath).fileName();
+		    QString destFile = destDir + fileName;
+			if (QFile::exists(destFile))
 				conflictCount++;
 		}
 	}
@@ -1198,9 +1200,11 @@ void CModListView::installMaps(QStringList maps)
 		else
 		{
 			// Single map file
-			QString fileName = map.section('/', -1, -1);
+			QString srcPath = Helper::getRealPath(map);
+			QString fileName = QFileInfo(srcPath).fileName();
 			QString destFile = destDir + fileName;
-			logGlobal->info("Importing map '%s'", map.toStdString());
+
+			logGlobal->info("Importing map '%s'", srcPath.toStdString());
 
 			if (QFile::exists(destFile))
 			{

+ 26 - 1
launcher/modManager/modstateitemmodel_moc.cpp

@@ -276,7 +276,7 @@ bool CModFilterModel::filterMatchesCategory(const QModelIndex & source) const
 			return !mod.isInstalled();
 		case ModFilterMask::INSTALLED:
 			return mod.isInstalled();
-		case ModFilterMask::UPDATEABLE:
+		case ModFilterMask::UPDATABLE:
 			return mod.isUpdateAvailable();
 		case ModFilterMask::ENABLED:
 			return mod.isInstalled() && base->model->isModEnabled(modID);
@@ -320,6 +320,31 @@ bool CModFilterModel::filterAcceptsRow(int source_row, const QModelIndex & sourc
 	return false;
 }
 
+bool CModFilterModel::lessThan(const QModelIndex & source_left, const QModelIndex & source_right) const
+{
+	if(source_left.column() != ModFields::STATUS_ENABLED)
+		return QSortFilterProxyModel::lessThan(source_left, source_right);
+
+	const auto leftMod = base->model->getMod(base->modIndexToName(source_left));
+	const auto rightMod = base->model->getMod(base->modIndexToName(source_right));
+
+	const auto isLeftEnabled = base->model->isModEnabled(leftMod.getID());
+	const auto isRightEnabled = base->model->isModEnabled(rightMod.getID());
+	if(!isLeftEnabled && isRightEnabled)
+		return true;
+	if(isLeftEnabled && !isRightEnabled)
+		return false;
+
+	const auto isLeftInstalled = leftMod.isInstalled();
+	const auto isRightInstalled = rightMod.isInstalled();
+	if(!isLeftInstalled && isRightInstalled)
+		return true;
+	if(isLeftInstalled && !isRightInstalled)
+		return false;
+
+	return QSortFilterProxyModel::lessThan(source_left.siblingAtColumn(ModFields::NAME), source_right.siblingAtColumn(ModFields::NAME));
+}
+
 CModFilterModel::CModFilterModel(ModStateItemModel * model, QObject * parent)
 	: QSortFilterProxyModel(parent), base(model), filterMask(ModFilterMask::ALL)
 {

+ 3 - 1
launcher/modManager/modstateitemmodel_moc.h

@@ -32,7 +32,7 @@ enum class ModFilterMask : uint8_t
 	ALL,
 	AVAILABLE,
 	INSTALLED,
-	UPDATEABLE,
+	UPDATABLE,
 	ENABLED,
 	DISABLED
 };
@@ -97,6 +97,8 @@ class CModFilterModel final : public QSortFilterProxyModel
 
 	bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override;
 
+	bool lessThan(const QModelIndex & source_left, const QModelIndex & source_right) const override;
+
 public:
 	void setTypeFilter(ModFilterMask filterMask);
 

+ 54 - 22
lib/mapping/CDrawRoadsOperation.cpp

@@ -20,7 +20,8 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-const std::vector<CDrawLinesOperation::LinePattern> CDrawLinesOperation::patterns =
+template <typename T>
+const std::vector<typename CDrawLinesOperation<T>::LinePattern> CDrawLinesOperation<T>::patterns =
 {
 	//single tile. fall-back pattern
 	{
@@ -156,34 +157,47 @@ static bool ruleIsAny(const std::string & rule)
 #endif
 
 ///CDrawLinesOperation
-CDrawLinesOperation::CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, vstd::RNG * gen):
+template <typename T>
+CDrawLinesOperation<T>::CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, T lineType, vstd::RNG * gen):
 	CMapOperation(map),
 	terrainSel(std::move(terrainSel)),
+	lineType(lineType),
 	gen(gen)
 {
 }
 
 ///CDrawRoadsOperation
 CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, vstd::RNG * gen):
-	CDrawLinesOperation(map, terrainSel,gen),
-	roadType(roadType)
-{
-}
+	CDrawLinesOperation(map, terrainSel,roadType, gen)
+{}
 
 ///CDrawRiversOperation
 CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId riverType, vstd::RNG * gen):
-	CDrawLinesOperation(map, terrainSel, gen),
-	riverType(riverType)
+	CDrawLinesOperation(map, terrainSel, riverType, gen)
+{}
+
+template <typename T>
+void CDrawLinesOperation<T>::execute()
 {
+	for(const auto & pos : terrainSel.getSelectedItems())
+	{
+		auto identifier = getIdentifier(map->getTile(pos));
+		if (formerState.find(identifier) == formerState.end())
+			formerState.insert({identifier, CTerrainSelection(terrainSel.getMap())});
+		formerState.at(identifier).select(pos);
+	}
+
+	drawLines(terrainSel, lineType);
 }
 
-void CDrawLinesOperation::execute()
+template <typename T>
+void CDrawLinesOperation<T>::drawLines(CTerrainSelection selection, T type)
 {
 	std::set<int3> invalidated;
 
-	for(const auto & pos : terrainSel.getSelectedItems())
+	for(const auto & pos : selection.getSelectedItems())
 	{
-		executeTile(map->getTile(pos));
+		executeTile(map->getTile(pos), type);
 
 		auto rect = extendTileAroundSafely(pos);
 		rect.forEach([&invalidated](const int3 & pos)
@@ -195,17 +209,23 @@ void CDrawLinesOperation::execute()
 	updateTiles(invalidated);
 }
 
-void CDrawLinesOperation::undo()
+template <typename T>
+void CDrawLinesOperation<T>::undo()
 {
-  //TODO
+	for (auto const& typeToSelection : formerState)
+	{
+		drawLines(typeToSelection.second, typeToSelection.first);
+	}
 }
 
-void CDrawLinesOperation::redo()
+template <typename T>
+void CDrawLinesOperation<T>::redo()
 {
-  //TODO
+  drawLines(terrainSel, lineType);
 }
 
-void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const
+template <typename T>
+void CDrawLinesOperation<T>::flipPattern(LinePattern& pattern, int flip) const
 {
 	//todo: use cashing here and also in terrain patterns
 
@@ -233,7 +253,8 @@ void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const
 	}
 }
 
-void CDrawLinesOperation::updateTiles(std::set<int3> & invalidated)
+template <typename T>
+void CDrawLinesOperation<T>::updateTiles(std::set<int3> & invalidated)
 {
 	for(const int3 & coord : invalidated)
 	{
@@ -264,7 +285,8 @@ void CDrawLinesOperation::updateTiles(std::set<int3> & invalidated)
 	}
 }
 
-CDrawLinesOperation::ValidationResult CDrawLinesOperation::validateTile(const LinePattern & pattern, const int3 & pos)
+template <typename T>
+typename CDrawLinesOperation<T>::ValidationResult CDrawLinesOperation<T>::validateTile(const LinePattern & pattern, const int3 & pos)
 {
 	ValidationResult result(false);
 
@@ -342,14 +364,14 @@ std::string CDrawRiversOperation::getLabel() const
 	return "Draw Rivers";
 }
 
-void CDrawRoadsOperation::executeTile(TerrainTile & tile)
+void CDrawRoadsOperation::executeTile(TerrainTile & tile, RoadId type)
 {
-	tile.roadType = roadType;
+	tile.roadType = type;
 }
 
-void CDrawRiversOperation::executeTile(TerrainTile & tile)
+void CDrawRiversOperation::executeTile(TerrainTile & tile, RiverId type)
 {
-	tile.riverType = riverType;
+	tile.riverType = type;
 }
 
 bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const
@@ -398,4 +420,14 @@ void CDrawRiversOperation::updateTile(TerrainTile & tile, const LinePattern & pa
 	tile.extTileFlags = (tile.extTileFlags & 0b00111111) | (flip << 2);
 }
 
+RiverId CDrawRiversOperation::getIdentifier(TerrainTile & tile) const
+{
+	return tile.riverType;
+}
+
+RoadId CDrawRoadsOperation::getIdentifier(TerrainTile & tile) const
+{
+	return tile.roadType;
+}
+
 VCMI_LIB_NAMESPACE_END

+ 22 - 14
lib/mapping/CDrawRoadsOperation.h

@@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 struct TerrainTile;
 
-class CDrawLinesOperation : public CMapOperation
+template <typename T> class CDrawLinesOperation : public CMapOperation
 {
 public:
 	void execute() override;
@@ -41,14 +41,15 @@ protected:
 		int flip;
 	};
 
-	CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, vstd::RNG * gen);
+	CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, T lineType, vstd::RNG * gen);
 
-	virtual void executeTile(TerrainTile & tile) = 0;
-	virtual bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const = 0;
+	virtual void executeTile(TerrainTile & tile, T type) = 0;
+	virtual bool canApplyPattern(const LinePattern & pattern) const = 0;
 	virtual bool needUpdateTile(const TerrainTile & tile) const = 0;
 	virtual bool tileHasSomething(const int3 & pos) const = 0;
-	virtual void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) = 0;
-	
+	virtual void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) = 0;
+	virtual T getIdentifier(TerrainTile & tile) const = 0;
+
 	static const std::vector<LinePattern> patterns;
 	
 	void flipPattern(LinePattern & pattern, int flip) const;
@@ -58,38 +59,45 @@ protected:
 	ValidationResult validateTile(const LinePattern & pattern, const int3 & pos);
 	
 	CTerrainSelection terrainSel;
+	T lineType;
 	vstd::RNG * gen;
+	std::map<T, CTerrainSelection> formerState;
+
+private:
+	void drawLines(CTerrainSelection selection, T type);
 };
 
-class CDrawRoadsOperation : public CDrawLinesOperation
+class CDrawRoadsOperation : public CDrawLinesOperation<RoadId>
 {
 public:
 	CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, vstd::RNG * gen);
 	std::string getLabel() const override;
 	
 protected:
-	void executeTile(TerrainTile & tile) override;
-	bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const override;
+	void executeTile(TerrainTile & tile, RoadId type) override;
+	bool canApplyPattern(const LinePattern & pattern) const override;
 	bool needUpdateTile(const TerrainTile & tile) const override;
 	bool tileHasSomething(const int3 & pos) const override;
-	void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
+	void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) override;
+	RoadId getIdentifier(TerrainTile & tile) const override;
 	
 private:
 	RoadId roadType;
 };
 
-class CDrawRiversOperation : public CDrawLinesOperation
+class CDrawRiversOperation : public CDrawLinesOperation<RiverId>
 {
 public:
 	CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId roadType, vstd::RNG * gen);
 	std::string getLabel() const override;
 	
 protected:
-	void executeTile(TerrainTile & tile) override;
-	bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const override;
+	void executeTile(TerrainTile & tile, RiverId type) override;
+	bool canApplyPattern(const LinePattern & pattern) const override;
 	bool needUpdateTile(const TerrainTile & tile) const override;
 	bool tileHasSomething(const int3 & pos) const override;
-	void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
+	void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) override;
+	RiverId getIdentifier(TerrainTile & tile) const override;
 	
 private:
 	RiverId riverType;

+ 22 - 6
lib/mapping/CMapOperation.cpp

@@ -103,22 +103,38 @@ void CDrawTerrainOperation::execute()
 	for(const auto & pos : terrainSel.getSelectedItems())
 	{
 		auto & tile = map->getTile(pos);
-		tile.terrainType = terType;
+		if (formerState.find(tile.terrainType) == formerState.end())
+			formerState.insert({tile.terrainType, CTerrainSelection(terrainSel.getMap())});
+		formerState.at(tile.terrainType).select(pos);
+	}
+	drawTerrain(terType, terrainSel);
+}
+
+void CDrawTerrainOperation::drawTerrain(TerrainId terrainType, CTerrainSelection selection)
+{
+	for(const auto & pos : selection.getSelectedItems())
+	{
+		auto & tile = map->getTile(pos);
+		tile.terrainType = terrainType;
 		invalidateTerrainViews(pos);
 	}
 
-	updateTerrainTypes();
+	updateTerrainTypes(selection);
 	updateTerrainViews();
+	invalidatedTerViews.clear();
 }
 
 void CDrawTerrainOperation::undo()
 {
-	//TODO
+	for (auto const& typeToSelection : formerState)
+	{
+		drawTerrain(typeToSelection.first, typeToSelection.second);
+	}
 }
 
 void CDrawTerrainOperation::redo()
 {
-	//TODO
+	drawTerrain(terType, terrainSel);
 }
 
 std::string CDrawTerrainOperation::getLabel() const
@@ -126,9 +142,9 @@ std::string CDrawTerrainOperation::getLabel() const
 	return "Draw Terrain";
 }
 
-void CDrawTerrainOperation::updateTerrainTypes()
+void CDrawTerrainOperation::updateTerrainTypes(CTerrainSelection selection)
 {
-	auto positions = terrainSel.getSelectedItems();
+	auto positions = selection.getSelectedItems();
 	while(!positions.empty())
 	{
 		const auto & centerPos = *(positions.begin());

+ 3 - 1
lib/mapping/CMapOperation.h

@@ -94,7 +94,8 @@ private:
 		InvalidTiles() : centerPosValid(false) { }
 	};
 
-	void updateTerrainTypes();
+	void drawTerrain(TerrainId terrain, CTerrainSelection selection);
+	void updateTerrainTypes(CTerrainSelection selection);
 	void invalidateTerrainViews(const int3 & centerPos);
 	InvalidTiles getInvalidTiles(const int3 & centerPos) const;
 
@@ -106,6 +107,7 @@ private:
 
 	CTerrainSelection terrainSel;
 	TerrainId terType;
+	std::map<TerrainId, CTerrainSelection> formerState;
 	int decorationsPercentage;
 	vstd::RNG* gen;
 	std::set<int3> invalidatedTerViews;

+ 8 - 7
scripting/erm/ERMInterpreter.cpp

@@ -77,7 +77,7 @@ namespace ERMConverter
 			}
 			else if(isMacro())
 			{
-				return boost::to_string(boost::format("M['%s']") % macro);
+				return (boost::format("M['%s']") % macro).str();
 			}
 			else if(isSpecial() && (name.size() == 1))
 			{
@@ -206,7 +206,7 @@ namespace ERMConverter
 		}
 		std::string operator()(const int & flag) const
 		{
-			return boost::to_string(boost::format("F['%d']") % flag);
+			return (boost::format("F['%d']") % flag).str();
 		}
 	};
 
@@ -801,14 +801,14 @@ namespace ERMConverter
 						fmt % target % v.str() % opt;
 						put(fmt.str());
 					}
-					
+
 					for(int i = paramIndex; i < trig.params->size(); i++)
 					{
 						opt = std::visit(VR_X(), (*trig.params)[i]);
 						if(i > paramIndex) put(",");
 						put(opt);
 					}
-					
+
 					putLine(")");
 				}
 				break;
@@ -1183,7 +1183,7 @@ namespace ERMConverter
 		}
 		void operator()(const boost::recursive_wrapper<VNode> & opt) const;
 
-		void operator()(const VSymbol & opt) const 
+		void operator()(const VSymbol & opt) const
 		{
 			(*out) << "\"" << opt.text << "\"";
 		}
@@ -1589,7 +1589,7 @@ namespace VERMInterpreter
 		struct OptionConverterVisitor
 		{
 			VOption operator()(const boost::recursive_wrapper<ERM::TVExp>& cmd) const
-			{ 
+			{
 				return boost::recursive_wrapper<VNode>(VNode(cmd.get()));
 			}
 			VOption operator()(const ERM::TSymbol & cmd) const
@@ -1599,7 +1599,7 @@ namespace VERMInterpreter
 				else
 					return boost::recursive_wrapper<VNode>(VNode(cmd));
 			}
-			VOption operator()(const char & cmd) const 
+			VOption operator()(const char & cmd) const
 			{
 				return TLiteral(cmd);
 			}
@@ -1732,6 +1732,7 @@ namespace VERMInterpreter
 	}
 	VermTreeIterator & VermTreeIterator::operator=( const VOptionList & opt )
 	{
+		// TODO: warning: all paths through this function will call itself [-Winfinite-recursion]
 		return *this = opt;
 	}
 	VOption & VermTreeIterator::getAsItem()

+ 2 - 2
server/CVCMIServer.h

@@ -36,14 +36,14 @@ class GlobalLobbyProcessor;
 
 class CVCMIServer : public LobbyInfo, public INetworkServerListener, public INetworkTimerListener, public IGameServer
 {
-	/// Network server instance that receives and processes incoming connections on active socket
-	std::unique_ptr<INetworkServer> networkServer;
 	std::unique_ptr<GlobalLobbyProcessor> lobbyProcessor;
 
 	std::chrono::steady_clock::time_point gameplayStartTime;
 	std::chrono::steady_clock::time_point lastTimerUpdateTime;
 
 	std::unique_ptr<INetworkHandler> networkHandler;
+	/// Network server instance that receives and processes incoming connections on active socket
+	std::unique_ptr<INetworkServer> networkServer;
 
 	EServerState state = EServerState::LOBBY;