diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 2870feba1..c9f8665ce 100644 --- a/client/windows/GUIClasses.cpp +++ b/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 += " "; diff --git a/launcher/lib/innoextract b/launcher/lib/innoextract index 98bb55798..96e9566a3 160000 --- a/launcher/lib/innoextract +++ b/launcher/lib/innoextract @@ -1 +1 @@ -Subproject commit 98bb55798a77c0346b12a1dbb53fe4d3e0379d66 +Subproject commit 96e9566a35fb51ebf13ffbdadfd49a93c1ae5c1a diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index d3c1ab6a8..4c68ae50f 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/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)) { diff --git a/launcher/modManager/modstateitemmodel_moc.cpp b/launcher/modManager/modstateitemmodel_moc.cpp index 4ae93f6ec..7e1084983 100644 --- a/launcher/modManager/modstateitemmodel_moc.cpp +++ b/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) { diff --git a/launcher/modManager/modstateitemmodel_moc.h b/launcher/modManager/modstateitemmodel_moc.h index 6b0a64656..29f778aa0 100644 --- a/launcher/modManager/modstateitemmodel_moc.h +++ b/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); diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 32625d9c0..cbe0997b3 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -20,7 +20,8 @@ VCMI_LIB_NAMESPACE_BEGIN -const std::vector CDrawLinesOperation::patterns = +template +const std::vector::LinePattern> CDrawLinesOperation::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 +CDrawLinesOperation::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 +void CDrawLinesOperation::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 +void CDrawLinesOperation::drawLines(CTerrainSelection selection, T type) { std::set 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 +void CDrawLinesOperation::undo() { - //TODO + for (auto const& typeToSelection : formerState) + { + drawLines(typeToSelection.second, typeToSelection.first); + } } -void CDrawLinesOperation::redo() +template +void CDrawLinesOperation::redo() { - //TODO + drawLines(terrainSel, lineType); } -void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const +template +void CDrawLinesOperation::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 & invalidated) +template +void CDrawLinesOperation::updateTiles(std::set & invalidated) { for(const int3 & coord : invalidated) { @@ -264,7 +285,8 @@ void CDrawLinesOperation::updateTiles(std::set & invalidated) } } -CDrawLinesOperation::ValidationResult CDrawLinesOperation::validateTile(const LinePattern & pattern, const int3 & pos) +template +typename CDrawLinesOperation::ValidationResult CDrawLinesOperation::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 diff --git a/lib/mapping/CDrawRoadsOperation.h b/lib/mapping/CDrawRoadsOperation.h index 7e9ea754d..21f4ca4ed 100644 --- a/lib/mapping/CDrawRoadsOperation.h +++ b/lib/mapping/CDrawRoadsOperation.h @@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN struct TerrainTile; -class CDrawLinesOperation : public CMapOperation +template 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 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 formerState; + +private: + void drawLines(CTerrainSelection selection, T type); }; -class CDrawRoadsOperation : public CDrawLinesOperation +class CDrawRoadsOperation : public CDrawLinesOperation { 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 { 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; diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 2cf46f200..d161f750d 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/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()); diff --git a/lib/mapping/CMapOperation.h b/lib/mapping/CMapOperation.h index 1e6d1ad8e..b9d2e3e1d 100644 --- a/lib/mapping/CMapOperation.h +++ b/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 formerState; int decorationsPercentage; vstd::RNG* gen; std::set invalidatedTerViews; diff --git a/scripting/erm/ERMInterpreter.cpp b/scripting/erm/ERMInterpreter.cpp index 664b86d3d..f3bcdd878 100644 --- a/scripting/erm/ERMInterpreter.cpp +++ b/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 & 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& cmd) const - { + { return boost::recursive_wrapper(VNode(cmd.get())); } VOption operator()(const ERM::TSymbol & cmd) const @@ -1599,7 +1599,7 @@ namespace VERMInterpreter else return boost::recursive_wrapper(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() diff --git a/server/CVCMIServer.h b/server/CVCMIServer.h index dbabf63a1..311e10db2 100644 --- a/server/CVCMIServer.h +++ b/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 networkServer; std::unique_ptr lobbyProcessor; std::chrono::steady_clock::time_point gameplayStartTime; std::chrono::steady_clock::time_point lastTimerUpdateTime; std::unique_ptr networkHandler; + /// Network server instance that receives and processes incoming connections on active socket + std::unique_ptr networkServer; EServerState state = EServerState::LOBBY;