From fdfcc2d575e845a32ffe2dfc0b330a686e92dcc0 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Tue, 27 Oct 2015 14:13:47 +0100 Subject: Add support for individual pack versions per scenario --- src/CRSMConfig.hpp | 2 + src/CRSMPackCompatibility.cpp | 169 +++++++++++++++++++++++++++++++++++++- src/CRSMPackCompatibility.hpp | 39 +++++++-- src/CrServerManager.pro | 6 +- src/crsm.cpp | 186 ++++++++++++++++++++++++++++++++++++++++-- src/crsm.hpp | 12 +++ 6 files changed, 396 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/CRSMConfig.hpp b/src/CRSMConfig.hpp index 0494aaf..1aee360 100644 --- a/src/CRSMConfig.hpp +++ b/src/CRSMConfig.hpp @@ -10,6 +10,7 @@ public: String CommandSign = "!"; String StatsFile = "CrServerManager.stats"; String SessionFile = "CrServerManager.session"; + String PacksFile = "CrServerManager.packs"; } CRSM; struct { @@ -88,6 +89,7 @@ public: ConfigVal(CRSM.CommandSign), ConfigVal(CRSM.StatsFile), ConfigVal(CRSM.SessionFile), + ConfigVal(CRSM.PacksFile), diff --git a/src/CRSMPackCompatibility.cpp b/src/CRSMPackCompatibility.cpp index 481cf44..cea57f7 100644 --- a/src/CRSMPackCompatibility.cpp +++ b/src/CRSMPackCompatibility.cpp @@ -1,7 +1,172 @@ -#include "PackCompatibility.hpp" +#include "CRSMPackCompatibility.hpp" -PackCompatibility::PackCompatibility() +#include + +void CRSMPackCompatibility::clear() { + auto configVals = configValues; + *this = CRSMPackCompatibility(); + configValues = configVals; +} + +QString CRSMPackCompatibility::linkScenarioPacks(const QString &scenario) +{ + QStringList parts; + parts.append(scenario); + QString ret; + int position = scenario.length(); + while((position = scenario.lastIndexOf('/', position - 1)) != -1) + { + parts.append(scenario.left(position)); + } + + QMap packs = PackDefaultVersion; + foreach(const QString& filePathPart, parts) + { + foreach(const QString& packVersion, ScenarioPacks.value(filePathPart)) + { + packs[PackVersions[packVersion]] = packVersion; + } + } + foreach(const QString& packName, packs.keys()) + { + QFile packFile(clonkPath + packName); + if(packFile.exists()) + { + packFile.remove(); + } + if(!QFile::link(clonkPath + packs[packName], clonkPath + packName)) + { + ret.append("Warning: Could not link pack \"" + packName + "\" to \"" + packs[packName] + "\".\n"); + } + } + + return ret; } +QString CRSMPackCompatibility::read(const QString &fileName, const QString& clonkPath, bool writeDefault) +{ + this->clonkPath = clonkPath; + QString ret = ConfigBase::read(fileName, writeDefault); + + foreach(const QString& packVersion, PackVersions.keys()) + { + ret.append(checkPackVersion(packVersion, PackVersions[packVersion])); + } + + foreach(const QString& scenario, ScenarioPacks.keys()) + { + foreach(const QString& scenarioPack, ScenarioPacks[scenario]) + { + ret.append(checkScenarioPack(scenarioPack, scenario)); + } + } + + return ret; +} + +QString CRSMPackCompatibility::addPackVersion(const QString &packVersion, const QString &pack) +{ + PackVersions[packVersion] = pack; + if(!PackDefaultVersion.contains(pack)) + { + PackDefaultVersion[pack] = packVersion; + } + return checkPackVersion(packVersion, pack); +} + +QString CRSMPackCompatibility::deletePackVersion(const QString &packVersion) +{ + if(PackVersions.contains(packVersion)) + { + const QString& pack = PackVersions.value(packVersion); + PackVersions.remove(packVersion); + if(PackVersions.values().count(pack) == 0) + { + PackDefaultVersion.remove(pack); + } + else if(PackDefaultVersion.value(pack) == packVersion) + { + PackDefaultVersion[pack] = PackVersions.key(pack); + return "Warning: Changing default version of \"" + pack + "\" to \"" + PackDefaultVersion[pack] + "\".\n"; + } + return ""; + } + else + { + return "Error: Can not remove unknown PackVersion."; + } +} + +QString CRSMPackCompatibility::setDefaultPackVersion(const QString &packVersion, const QString &pack) +{ + PackDefaultVersion[pack] = packVersion; + QString ret = addPackVersion(packVersion, pack); + return ret; +} + +QString CRSMPackCompatibility::addScenarioPackVersion(const QString &packVersion, const QString &scenario) +{ + QString ret = checkScenarioPack(packVersion, scenario); + if(ret.isEmpty()) + { + QString pack = PackVersions.value(packVersion); + foreach(const QString& scenarioPack, ScenarioPacks[scenario]) + { + if(pack == PackVersions.value(scenarioPack)) + { + ScenarioPacks[scenario].removeAll(scenarioPack); + ret = "Overwriting old PackVersion \"" + scenarioPack + "\" with \"" + packVersion + "\".\n"; + } + } + } + + ScenarioPacks[scenario].append(packVersion); + return ret; +} + +QString CRSMPackCompatibility::deleteScenarioPackVersion(const QString &packVersion, const QString &scenario) +{ + if(!ScenarioPacks.contains(scenario)) + { + return "Warning: The scenario \"" + scenario + "\" has no ScenarioPacks defined.\n"; + } + else if(!ScenarioPacks[scenario].contains(packVersion)) + { + return "Warning: The scenario \"" + scenario + "\" has no ScenarioPack \"" + packVersion + "\" defined.\n"; + } + else + { + ScenarioPacks[scenario].removeAll(packVersion); + if(ScenarioPacks[scenario].length() == 0) + { + ScenarioPacks.remove(scenario); + } + return ""; + } +} + +QString CRSMPackCompatibility::checkPackVersion(const QString &packVersion, const QString &pack) +{ + if(!QFile(clonkPath + packVersion).exists()) + { + return "Warning: PackVersion \"" + packVersion + "\" of pack \"" + pack + "\" does not exist.\n"; + } + else + { + return ""; + } +} + +QString CRSMPackCompatibility::checkScenarioPack(const QString &packVersion, const QString &scenario) +{ + if(!PackVersions.contains(packVersion)) + { + return "Warning: Unknown ScenarioPack \"" + packVersion + "\" of scenario \"" + scenario + "\" will not be linked.\n"; + } + else + { + return ""; + } +} diff --git a/src/CRSMPackCompatibility.hpp b/src/CRSMPackCompatibility.hpp index eddc350..a35ed95 100644 --- a/src/CRSMPackCompatibility.hpp +++ b/src/CRSMPackCompatibility.hpp @@ -1,11 +1,36 @@ -#ifndef PACKCOMPATIBILITY_HPP -#define PACKCOMPATIBILITY_HPP +#pragma once +#include "ConfigBase.hpp" - -class PackCompatibility : public ConfigBase +class CRSMPackCompatibility : public ConfigBase { public: - PackCompatibility(); -}; + Map(String, String) PackDefaultVersion; + Map(String, String) PackVersions; + Map(String, List(String)) ScenarioPacks; + + CRSMPackCompatibility() : ConfigBase::ConfigBase({ + ConfigVal(PackDefaultVersion), + ConfigVal(PackVersions), + ConfigVal(ScenarioPacks) + }) { } + + void clear(); + + QString linkScenarioPacks(const QString& scenario); -#endif // PACKCOMPATIBILITY_HPP + QString read(const QString &fileName, const QString &clonkPath, bool writeDefault = true); + + QString addPackVersion(const QString& packVersion, const QString& pack); + QString deletePackVersion(const QString& packVersion); + QString setDefaultPackVersion(const QString& packVersion, const QString& pack); + + QString addScenarioPackVersion(const QString& packVersion, const QString& scenario); + QString deleteScenarioPackVersion(const QString& packVersion, const QString& scenario); + +protected: + QString checkPackVersion(const QString& packVersion, const QString& pack); + QString checkScenarioPack(const QString& packVersion, const QString& scenario); + +private: + QString clonkPath; +}; diff --git a/src/CrServerManager.pro b/src/CrServerManager.pro index fa0a7a2..4c27668 100644 --- a/src/CrServerManager.pro +++ b/src/CrServerManager.pro @@ -22,7 +22,8 @@ SOURCES += main.cpp \ ProcessManager.cpp \ ConfigBase.cpp \ Util.cpp \ - CRSMStats.cpp + CRSMStats.cpp \ + CRSMPackCompatibility.cpp HEADERS += \ CmdFunctionRef.hpp \ @@ -32,7 +33,8 @@ HEADERS += \ CRSMConfig.hpp \ ConfigBase.hpp \ Util.hpp \ - CRSMStats.hpp + CRSMStats.hpp \ + CRSMPackCompatibility.hpp equals(QT_ARCH, "x86_64"):linux-*: DEFINES += Q_OS_LINUX64 QMAKE_CXXFLAGS *= -std=c++11 -Wall -Wextra -Werror -Wunused diff --git a/src/crsm.cpp b/src/crsm.cpp index def9231..a6262fa 100644 --- a/src/crsm.cpp +++ b/src/crsm.cpp @@ -309,8 +309,7 @@ void CRSM::scenarioFinished() { if(finish) { - writeConfig(); - Stats.write(); + writeFiles(); if(processManager != nullptr) processManager->exit(); if(connection != 0) { @@ -616,7 +615,7 @@ void CRSM::startScen(const ScenarioSettings &scen, QStringList argList) scoreboardFile.open(QFile::WriteOnly); scoreboardFile.close(); - Session.Scenario= scen; + Session.Scenario = scen; Session.IRC.UseIngameChat = Config.IRC.UseIngameChat; Session.State = CRSMSession::Lobby; ircSetIngameChannelTopic(); @@ -633,6 +632,7 @@ void CRSM::startScen(const ScenarioSettings &scen, QStringList argList) } argList << filename; processManager->setWorkingDirectory(Config.Auto.Volatile.Clonk.Directory); + out(Packs.linkScenarioPacks(filename)); processManager->start(Config.Clonk.Server.Executable, argList); } @@ -1343,6 +1343,17 @@ void CRSM::setupCmds() addCommand("config get", &CRSM::getConfigValue, Management, UserType::Max, "Gibt den aktuellen Wert von der Konfiguration an.", ""); addCommand("config set", &CRSM::setConfigValue, Management, UserType::Max, "Setzt einen Konfigurationswert.", "", "Setzt einen Konfigurationswert. Der Wert wird wie eine Zeile in der Konfigurationsdatei angegeben."); + addCommandGroup("packs", Management, UserType::Max, "Über die packs-Befehlsgruppe lassen sich mehrere Versionen eines Objektpakets für unterschiedliche Szenarien verwalten."); + addCommand("packs list", &CRSM::packsList, Management, UserType::Max, "Listet alle bekannten Packs und ihre Versionen auf."); + addCommandGroup("packs versions", Management, UserType::Max, "Über die packs versions-Befehlsgruppe werden die einzelnen bekannten Packs und vorhandenen Versionen verwaltet."); + addCommand("packs versions add", &CRSM::packsVersionsAdd, Management, UserType::Max, "Fügt eine neue für das hinzu.", " = "); + addCommand("packs versions delete", &CRSM::packsVersionsDelete, Management, UserType::Max, "Löscht eine .", ""); + addCommand("packs versions default", &CRSM::packsVersionsDefault, Management, UserType::Max, "Fragt die Packversion ab, die standardmäßig für das verwendet wird, oder setzt sie, wenn angegeben wird.", " [= ]"); + addCommandGroup("packs scenarios", Management, UserType::Max, "Über die packs scenarios-Befehlsgruppe werden die einzelnen Packversionen den Szenarien zugeteilt."); + addCommand("packs scenarios add", &CRSM::packsScenariosAdd, Management, UserType::Max, "Aktiviert für das die .", " "); + addCommand("packs scenarios delete", &CRSM::packsScenariosDelete, Management, UserType::Max, "Löscht für das die .", " "); + addCommand("packs scenarios list", &CRSM::packsScenariosList, Management, UserType::Max, "Listet alle Szenarien mit ihren Packversionen auf."); + addCommand("relist", &CRSM::relist, Management, UserType::Max, "Durchsucht veränderte Rundenordner erneut."); } @@ -1549,7 +1560,7 @@ void CRSM::exit() void CRSM::applyConfig() { - Stats.write(); + writeFiles(false, true); args.clear(); args << "/config:" + Config.Clonk.Server.Config; args << Config.Clonk.Server.Arguments.split(" "); @@ -1604,6 +1615,7 @@ void CRSM::applyConfig() } setupCmds(); out(Stats.read(Config.CRSM.StatsFile)); + out(Packs.read(Config.CRSM.PacksFile, Config.Auto.Volatile.Clonk.Directory)); } QString CRSM::scenarioFileName(QString name) @@ -1620,6 +1632,20 @@ CmdResult CRSM::callCommand(const CmdFunctionRef &func, const QString &args, con return ret; } +void CRSM::writeFiles(bool writeSession, bool writeNoConfig) +{ + if(writeSession) + { + Session.write(Config.CRSM.SessionFile); + } + Stats.write(); + Packs.write(); + if(!writeNoConfig) + { + writeConfig(); + } +} + CMD_FUNCTION_IMPL(help) bool longHelp = (args == "long"); if(args.isEmpty() || longHelp) @@ -2134,9 +2160,7 @@ CMD_FUNCTION_IMPL(exit) CMD_FUNCTION_IMPL(exitDetach) Config.Auto.ProcessManager.ReattachId = processManager->ID(); - writeConfig(); - Session.write(Config.CRSM.SessionFile); - Stats.write(); + writeFiles(true); connection->quit(Config.IRC.QuitMessage); QCoreApplication::quit(); return Success; @@ -2335,6 +2359,154 @@ CMD_FUNCTION_IMPL(getAdmin) return Success; } +CMD_FUNCTION_IMPL(packsList) + if(Packs.PackDefaultVersion.size() == 0) + { + respond(client, "Es sind noch keine speziellen Packversionen bekannt.\n"); + return Success; + } + QString response("Folgende Packs und ihre Versionen sind bekannt:\n"); + + QMap packVersions; + foreach(const QString& packVersion, Packs.PackVersions.keys()) + { + packVersions[Packs.PackVersions.value(packVersion)].append(packVersion); + } + + foreach(const QString& pack, Packs.PackDefaultVersion.keys()) + { + response.append("\t" + pack + "\t-\t" + packVersions[pack].join(", ") + "\n"); + } + + respond(client, response); + return Success; +} + +CMD_FUNCTION_IMPL(packsVersionsAdd) + const QStringList& argList = Util::splitEscaped(args, '='); + if(argList.length() != 2) + { + respond(client, "Eingabefehler! Siehe " + Config.CRSM.CommandSign + "help für mehr Informationen.\n"); + return SyntaxFail; + } + else + { + QString response = Packs.addPackVersion(argList.first().trimmed(), argList.at(1).trimmed()); + if(response.isEmpty()) + { + response = "PackVersion wurde erfolgreich eingetragen.\n"; + } + respond(client, response); + return Success; + } +} + +CMD_FUNCTION_IMPL(packsVersionsDelete) + QString pack = Packs.PackVersions[args]; + QString response = Packs.deletePackVersion(args); + if(response.isEmpty()) + { + response = "PackVersion \"" + args + "\" vom Pack \"" + pack + "\" wurde erfolgreich entfernt.\n"; + } + respond(client, response); + return Success; +} + +CMD_FUNCTION_IMPL(packsVersionsDefault) + const QStringList& argList = Util::splitEscaped(args, '='); + if(argList.length() != 2 && argList.length() != 1) + { + respond(client, "Eingabefehler! Siehe " + Config.CRSM.CommandSign + "help für mehr Informationen.\n"); + return SyntaxFail; + } + else if(argList.length() == 2) + { + QString oldDefault = Packs.PackDefaultVersion[argList.first().trimmed()]; + QString response = Packs.setDefaultPackVersion(argList.at(1).trimmed(), argList.first().trimmed()); + if(response.isEmpty()) + { + if(oldDefault.isEmpty()) + { + response = "Neues PackDefault wurde erfolgreich eingetragen.\n"; + } + else + { + response = "Altes PackDefault \"" + oldDefault + "\" wurde erfolgreich überschrieben.\n"; + } + } + respond(client, response); + return Success; + } + else + { + if(Packs.PackDefaultVersion.contains(args)) + { + respond(client, "Standardversion für \"" + args + "\" ist \"" + Packs.PackDefaultVersion.value(args) + "\".\n"); + } + else + { + respond(client, "Unbekanntes Pack: \"" + args + "\"!\n"); + } + return Success; + } +} + +CMD_FUNCTION_IMPL(packsScenariosAdd) + const QStringList& argList = Util::splitEscaped(args, ' '); + if(argList.length() != 2) + { + respond(client, "Eingabefehler! Siehe " + Config.CRSM.CommandSign + "help für mehr Informationen.\n"); + return SyntaxFail; + } + else + { + QString response = Packs.addScenarioPackVersion(argList.at(1).trimmed(), argList.first().trimmed()); + if(response.isEmpty()) + { + response = "Packversion für das Szenario wurde erfolgreich hinzugefügt.\n"; + } + respond(client, response); + return Success; + } +} + +CMD_FUNCTION_IMPL(packsScenariosDelete) + const QStringList& argList = Util::splitEscaped(args, ' '); + if(argList.length() != 2) + { + respond(client, "Eingabefehler! Siehe " + Config.CRSM.CommandSign + "help für mehr Informationen.\n"); + return SyntaxFail; + } + else + { + QString response = Packs.deleteScenarioPackVersion(argList.at(1).trimmed(), argList.first().trimmed()); + if(response.isEmpty()) + { + response = "Packversion für das Szenario wurde erfolgreich entfernt.\n"; + } + respond(client, response); + return Success; + } +} + +CMD_FUNCTION_IMPL(packsScenariosList) + if(Packs.ScenarioPacks.size() == 0) + { + respond(client, "Es sind noch keine Szenarios mit speziellen Packversionen bekannt.\n"); + return Success; + } + QString response("Folgende Szenarien mit speziellen Packversionen sind bekannt:\n"); + + foreach(const QString& scenario, Packs.ScenarioPacks.keys()) + { + response.append("\t" + scenario + "\t-\t" + Packs.ScenarioPacks.value(scenario).join(", ") + "\n"); + } + + respond(client, response); + + return Success; +} + IRC_CHECK_CALLBACK_IMPL(ircSayQuery) if(status <= 0) { diff --git a/src/crsm.hpp b/src/crsm.hpp index 63e6156..af3b5cf 100644 --- a/src/crsm.hpp +++ b/src/crsm.hpp @@ -22,6 +22,7 @@ #include "ProcessManager.hpp" #include "CRSMConfig.hpp" #include "CRSMStats.hpp" +#include "CRSMPackCompatibility.hpp" #define CONFIG_FILE_NAME "CrServerManager.conf" #define SESSION_FILE_NAME "CrServerManager.session" @@ -187,6 +188,7 @@ private: CRSMSession Session; CRSMStats Stats; + CRSMPackCompatibility Packs; QList userlist; QList autolist; @@ -275,6 +277,8 @@ private: QString scenarioFileName(QString name); CmdResult callCommand(const CmdFunctionRef& func, const QString& args, const ClientInfo& client, UserType userType); + void writeFiles(bool writeSession = false, bool writeNoConfig = false); + CMD_FUNCTION(help); CMD_FUNCTION(passToClonk); CMD_FUNCTION(passToClonkOnOff); @@ -326,6 +330,14 @@ private: CMD_FUNCTION(ircSay); CMD_FUNCTION(ircWatch); + CMD_FUNCTION(packsList); + CMD_FUNCTION(packsVersionsAdd); + CMD_FUNCTION(packsVersionsDelete); + CMD_FUNCTION(packsVersionsDefault); + CMD_FUNCTION(packsScenariosAdd); + CMD_FUNCTION(packsScenariosDelete); + CMD_FUNCTION(packsScenariosList); + IRC_CHECK_CALLBACK(ircSetAdmin); IRC_CHECK_CALLBACK(ircModCmd); IRC_CHECK_CALLBACK(ircSayQuery); -- cgit v1.2.3-54-g00ecf