diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2015-03-18 17:38:51 +0100 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2015-03-18 17:38:51 +0100 |
| commit | 8983d3b38421843db67a05edee180028959c1b51 (patch) | |
| tree | 904305965e9ba3baa27680d5d8b2a7b8dbea213e /crsm.cpp | |
| parent | fbe3c5fbe1327fd81e2eb8fe30a75c4cf5d7b35c (diff) | |
| download | manager-8983d3b38421843db67a05edee180028959c1b51.tar.gz manager-8983d3b38421843db67a05edee180028959c1b51.zip | |
Added ProcessManager, so Clonk can run independently from CRSM.
Added support for league with --league flag for !host.
Diffstat (limited to 'crsm.cpp')
| -rw-r--r-- | crsm.cpp | 255 |
1 files changed, 200 insertions, 55 deletions
@@ -17,7 +17,6 @@ CRSM::CRSM(QObject *parent) : qin = new QTextStream(stdin, QIODevice::ReadOnly); qout->setCodec(QTextCodec::codecForName("UTF-8")); - serverprocess = new QProcess; args << "/fullscreen" << "/config:config" << "/lobby:60" << "/nosignup"; current = 0; finish = false; @@ -27,16 +26,42 @@ CRSM::CRSM(QObject *parent) : listC4Folders(); readScenarios(); + if(settings.contains("ReattachId")) + { + processManager = new ProcessManager("CRSM-Clonkserver-", settings["ReattachId"]); + } + else + { + processManager = new ProcessManager("CRSM-Clonkserver-"); + } + + + if(!processManager->isOk()) + { + *qout << "Could not start Process Manager!" << endl; + settings.remove("ReattachId"); + writeConfig(); + return; + } + + settings["ReattachId"] = processManager->ID(); + writeConfig(); + + if(processManager->isRunning()) + { + writeToServer("Server Manager läuft wieder.\n"); + } + setupCmds(); connect(&greetMapper, SIGNAL(mapped(QString)), this, SLOT(greet(QString))); autoHost = settings["AutoHost"] == "true"; - connect(serverprocess, SIGNAL(readyRead()), this, SLOT(readServerOutput())); - connect(serverprocess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError())); - connect(serverprocess, SIGNAL(finished(int)), this, SLOT(scenarioFinished())); - QSocketNotifier *inNotifier = new QSocketNotifier(STDIN_FILENO,QSocketNotifier::Read,this); + connect(processManager, SIGNAL(readyRead()), this, SLOT(readServerOutput())); + //connect(processManager, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError())); + connect(processManager, SIGNAL(finished(int)), this, SLOT(scenarioFinished())); + QSocketNotifier *inNotifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read,this); connect(inNotifier, SIGNAL(activated(int)), this, SLOT(readInput())); QFile *reallog = new QFile(settings["ClonkDirectory"]+"CRSM.log"); @@ -69,6 +94,8 @@ CRSM::CRSM(QObject *parent) : { settings["IrcUseIngameChat"] = "false"; } + + ok = true; } CRSM::~CRSM() @@ -77,14 +104,19 @@ CRSM::~CRSM() void CRSM::start() { - if(autoHost) + if(autoHost && !processManager->isRunning()) nextScen(); } +bool CRSM::isOk() +{ + return ok; +} + void CRSM::readServerOutput() { QRegExp timeRemover("^>?\\s*\\[\\d\\d:\\d\\d:\\d\\d\\]\\s+(.*)$"); - QString what(serverprocess->readAll()); + QString what(processManager->readLine()); if(settings["ServerUsesReadline"] == "true") { @@ -116,12 +148,12 @@ void CRSM::readServerOutput() return; what = timeRemover.cap(1).trimmed(); - QRegExp userexp("^>?\\s*<(.*)\\|(\\d+)\\|([^>]*)>\\s+(.*)$"); + QRegExp userexp("^\\s*<(.*)\\|(\\d+)\\|([^>]*)>\\s+(.*)$"); if(userexp.exactMatch(what)) { QString user = userexp.cap(3); QString pcName = userexp.cap(1); - QString cuid = userexp.cap(2); + //QString cuid = userexp.cap(2); ClientInfo& info = clients[pcName]; if(user != settings["ServerNick"]) { @@ -204,24 +236,35 @@ void CRSM::readServerOutput() } if(--clientcount == 0 && userlist.length() > 0 && session["userwish"] != "true") { - serverprocess->closeWriteChannel(); + processManager->closeProgFifos(); } } } -void CRSM::processError() +/*void CRSM::processError() { - *qout << serverprocess->errorString() << endl; -} + *qout << processManager->errorString() << endl; +}*/ void CRSM::readInput() { QString what(qin->readLine()); + if(what == "/exitdetach" || what == "/exitupdate") + { + if(what == "/exitupdate") + { + writeToServer("Der Server Manager wird upgedatet. Befehle funktionieren temporär nicht.\n"); + } + settings["ReattachId"] = processManager->ID(); + writeConfig(); + QCoreApplication::quit(); + return; + } if(what == "/exit") { - serverprocess->closeWriteChannel(); + processManager->closeProgFifos(); + settings.remove("ReattachId"); finish = true; - cleanUp(); if(session["hosting"] != "true") scenarioFinished(); return; @@ -304,6 +347,7 @@ void CRSM::scenarioFinished() if(finish) { writeConfig(); + processManager->exit(); if(connection != 0) { connection->quit(settings["IrcQuitMessage"]); @@ -346,7 +390,11 @@ void CRSM::ircMessageReceived(IrcMessage *message) if(message->nick() == "NickServ") { QStringList split = message->parameters().at(1).split(' ', QString::SkipEmptyParts); - if(split.first() == "STATUS") + if(((IrcNoticeMessage*)message)->content().contains("nickname is registered")) + { + connection->sendCommand(IrcCommand::createMessage("NickServ", "IDENTIFY " + settings["IrcNick"] + " " + settings["IrcPassword"])); + } + else if(split.first() == "STATUS") { QString statusNick = split.at(1); int status = split.at(2).toInt(); @@ -463,8 +511,9 @@ void CRSM::greet(QString pcName) writeToServer(QString("Hallo " + info.nick + "!\n")); } -void CRSM::startScen(QString scen, QStringList argList) +void CRSM::startScen(const ScenarioSettings &scen, QStringList argList) { + QString filename; QFile lastScenFile(LAST_SCEN_FILE_NAME); QFile curScenFile(CUR_SCEN_FILE_NAME); curScenFile.open(QFile::ReadOnly); @@ -473,22 +522,33 @@ void CRSM::startScen(QString scen, QStringList argList) lastScenFile.close(); curScenFile.close(); curScenFile.open(QFile::WriteOnly); - curScenFile.write(scen.toUtf8()); + curScenFile.write(scen.name.toUtf8()); curScenFile.close(); QFile scoreboardFile(SCOREBOARD_FILE_NAME); scoreboardFile.open(QFile::WriteOnly); scoreboardFile.close(); - session["scenname"] = scen; + session["scenname"] = scen.name; session["IrcUseIngameChat"] = settings["IrcUseIngameChat"]; if(settings["IrcUseIngameChat"] == "true" && !settings["IrcIngameChannel"].isEmpty()) { connection->sendCommand(IrcCommand::createTopic(settings["IrcIngameChannel"], "Aktuelles Szenario: " + session["scenname"] + " | Ingamechat ist " + (session["IrcUseIngameChat"] == "true" ? "" : "de") + "aktviert.")); } - while(maps["Alias"].contains(scen)) - scen = maps["Alias"].value(scen); - serverprocess->setWorkingDirectory(QDir::currentPath()); - serverprocess->start(settings["ServerExecutable"], argList << scen); + filename = scen.name; + while(maps["Alias"].contains(filename)) + filename = maps["Alias"].value(filename); + //processManager->setWorkingDirectory(QDir::currentPath()); + if(scen.league) + { + argList << "/league"; + } + else + { + argList << "/noleague"; + } + argList << filename; + processManager->setWorkingDirectory(settings["ClonkDirectory"]); + processManager->start(settings["ServerExecutable"], argList); } void CRSM::readConfig() @@ -624,6 +684,7 @@ QMap<QString, QString> CRSM::defaultSettings() void CRSM::listC4Folders() { *qout << "Listing Contents of C4Folders..."; + qout->flush(); QDirIterator it(settings["ClonkDirectory"], QDirIterator::FollowSymlinks); for(; it.hasNext(); it.next()) { @@ -667,7 +728,8 @@ bool CRSM::scenExists(QString filePath) if(!exists) { QStringList split = filePath.split('/'); - if(split.length() == 2) + QString name = filePath.right(filePath.length() - split.first().length() - 1); + if(split.length() >= 2) { if(split.first().right(4) == ".c4f") { @@ -678,7 +740,7 @@ bool CRSM::scenExists(QString filePath) while(!lstFile.atEnd()) { QString line = lstFile.readLine().trimmed(); - if(line == split.last()) + if(line == name) { exists = true; break; @@ -740,21 +802,23 @@ QString CRSM::printQueue() { QString ret; if(userlist.length() == 0 && !autoHost) + { return "Die Warteschlange ist leer.\n"; + } + ret = "Folgende Szenarien befinden sich in der Warteschlange:\n"; if(autoHost) { - ret = "Folgende Szenarien befinden sich in der Warteschlange:\n"; for(int i = 0; i<settings["UserListLength"].toInt(); i++) { - ret += "\t"+QString::number(i+1)+". "+(userlist.length()>i?userlist.at(i):scenlist.at((i-userlist.length() + current)%scenlist.length()) + " (auto)")+"\n"; + ret += "\t"+QString::number(i+1)+". "+(userlist.length()>i?userlist.at(i).name + " (" + userlist.at(i).wishClient.toString() + ")" + (userlist.at(i).league ? " in der Liga" : ""):scenlist.at((i-userlist.length() + current)%scenlist.length()) + " (auto)")+"\n"; } } else { int i = 1; - foreach(const QString& scen, userlist) + foreach(const ScenarioSettings& scen, userlist) { - ret += "\t" + QString::number(i) + ". " + scen + "\n"; + ret += "\t" + QString::number(i) + ". " + scen.name + " (" + scen.wishClient.toString() + ")" + (scen.league ? " in der Liga" : "") + "\n"; ++i; } } @@ -771,7 +835,7 @@ QString CRSM::skipScen() { if(userlist.length() > 0) { - QString skipped = userlist.first(); + QString skipped = userlist.first().name + " (" + userlist.first().wishClient.toString() + ")"; userlist.removeFirst(); return skipped; } @@ -779,14 +843,19 @@ QString CRSM::skipScen() return ""; } -void CRSM::skipCurrent() +bool CRSM::skipCurrent() { - serverprocess->closeWriteChannel(); + if(processManager->isRunning()) + { + processManager->closeProgFifos(); + return true; + } + return false; } void CRSM::writeToServer(const QString &message) { - if(!serverprocess->isWritable()) + if(!processManager->isWritable()) return; int i = 0; QStringList split = message.split('\n', QString::KeepEmptyParts); @@ -813,7 +882,7 @@ void CRSM::writeToServer(const QString &message) linePart += "-"; } linePart += "\n"; - serverprocess->write(codec->fromUnicode(linePart)); + processManager->write(codec->fromUnicode(linePart)); if(settings["ServerUsesReadline"] == "true") { if(writtenToServer.length() > settings["ReadlineRereadLimit"].toInt()) @@ -821,7 +890,7 @@ void CRSM::writeToServer(const QString &message) writtenToServer += codec->fromUnicode(linePart); } } - serverprocess->write(codec->fromUnicode(line)); + processManager->write(codec->fromUnicode(line)); if(settings["ServerUsesReadline"] == "true") { if(writtenToServer.length() > settings["ReadlineRereadLimit"].toInt()) @@ -1052,7 +1121,7 @@ bool CRSM::cmd(const QString &name, const QString &args, const ClientInfo &clien void CRSM::rightsFailMessage(const ClientInfo &info, UserType minUserType) { - respond(info, "Nur ein " + userTypeStrings.value(minUserType) + " kann diesen Befehl verwenden.\n", RespondType::Private); + respond(info, "Nur ein " + userTypeStrings.value(minUserType) + " kann diesen Befehl verwenden.\n", RespondType::PrivateNotice); } UserType CRSM::clientUserType(const ClientInfo &client) @@ -1090,7 +1159,7 @@ void CRSM::setupCmds() addCommand("ingamechat", &CRSM::ircchat, IRC, Admin, "Schaltet den Irc-Ingame-Chat ein bzw. aus.", "<on¦off>"); } addCommand("queue", &CRSM::queue, Clonk | IRC, User, "Zeigt die nächsten " + settings["UserListLength"] + " Szenarien auf der Warteliste."); - addCommand("host", &CRSM::host, Clonk | IRC, User, "Nimmt das angegebene Szenario in die Wunschliste auf.", "<Szenarioname¦Alias>"); + addCommand("host", &CRSM::host, Clonk | IRC, User, "Nimmt das angegebene Szenario in die Wunschliste auf. Optional in der Liga, wenn \"--league\" angegeben wird.", "[--league] <Szenarioname¦Alias>"); addCommand("list", &CRSM::list, Clonk | IRC, User, "Listet alle definierten Aliase oder alle möglichen Szenarien und Ordner auf, bzw. alle Szenarien im Ordner oder Rundenordner.", "[Aliase¦Rundenordner[.c4f]]"); addCommand("clientlist", &CRSM::clientlist, Clonk | IRC, User, "Listet alle verbundenen Clients mit PC-Name und Chatnick auf."); addCommand("help", &CRSM::help, Clonk | IRC, User, "Zeigt die Hilfe an.", "[long¦Befehlsname]", "Listet alle verfügbaren Befehle auf. Mit long werden alle verfügbaren Befehle mit Kurzbeschreibung aufgelistet."); @@ -1100,8 +1169,6 @@ void CRSM::setupCmds() addCommand("plrteam", &CRSM::passToClonk, Clonk | IRC, Admin, "Ändert das Team eines Spielers.", "<Spieler> <neues Team>", "Verschiebt <Spieler> in das <neue Team>."); addCommand("pause", &CRSM::passToClonk, Clonk | IRC, Admin, "Pausiert das Spiel."); addCommand("unpause", &CRSM::passToClonk, Clonk | IRC, Admin, "Setzt das pausierte Spiel fort."); - addCommand("teamcolorson", &CRSM::passToClonk, Clonk | IRC, Admin, "Schaltet Teamfarben ein."); - addCommand("teamcolorsoff", &CRSM::passToClonk, Clonk | IRC, Admin, "Schaltet Teamfarben aus."); addCommand("observer", &CRSM::pcNamePassToClonk, Clonk | IRC, Admin, "Der angegebene Host muss zuschauen.", "<PC-Name¦Chatnick>"); addCommand("deactivate", &CRSM::pcNamePassToClonk, Clonk | IRC, Admin, "Deaktiviert den angegebenen Host.", "<PC-Name¦Chatnick>"); addCommand("activate", &CRSM::pcNamePassToClonk, Clonk | IRC, Admin, "Aktiviert den angegebenen Host.", "<PC-Name¦Chatnick>"); @@ -1113,10 +1180,11 @@ void CRSM::setupCmds() addCommand("nodebug", &CRSM::passToClonk, Clonk | IRC, Admin, "Deaktiviert den Debug-Modus zwingend für alle."); addCommand("autohost", &CRSM::autohost, Clonk | IRC, Moderator, "Deaktiviert den Debug-Modus zwingend für alle."); addCommand("noautohost", &CRSM::autohost, Clonk | IRC, Moderator, "Deaktiviert den Debug-Modus zwingend für alle."); + addCommand("set", &CRSM::set, Clonk | IRC, Admin, "Setzt diverse Einstellungen entsprechend dem /set Befehl von Clonk.", "<maxplayer¦password¦faircrew¦teamcolors¦runtimejoin> [on¦off¦<Passwort>¦<Spieleranzahl>]"); addCommand("skip", &CRSM::skip, Clonk | IRC, Moderator, "Entfernt das nächste Szenario aus der Wunschliste."); addCommand("next", &CRSM::next, Clonk | IRC, Moderator, "Versucht das aktuelle Szenario zu überspringen."); - addCommand("kill", &CRSM::kill, IRC, Moderator, "Tötet den Clonk-Server, vorausgesetzt es läuft einer.", "Tötet den Clonk-Server, vorausgesetzt es läuft einer. Bitte nur verwenden wenn " CMD_SIGN "next nicht funktioniert."); + addCommand("kill", &CRSM::kill, IRC, Moderator, "Tötet den Clonk-Server, vorausgesetzt es läuft einer.", "", "Tötet den Clonk-Server, vorausgesetzt es läuft einer. Bitte nur verwenden wenn " CMD_SIGN "next nicht funktioniert."); addCommand("clear", &CRSM::clear, Clonk | IRC, Moderator, "Löscht die Wunschliste."); addCommand("aliaswishes", &CRSM::aliaswishes, IRC, Moderator, "Zum geführten Bearbeiten der Aliaswünsche."); addCommand("newalias", &CRSM::newalias, IRC, Moderator, "Trägt <Alias> als Alias für <Szenario> ein.", "<Alias> = <Szenario>"); @@ -1161,7 +1229,12 @@ void CRSM::setIngameAdmin(const ClientInfo &client, const QString& newAdmin) { if(clients.contains(newAdmin)) { - sessionAdmin = clients.value(newAdmin); + const ClientInfo& info = clients.value(newAdmin); + if(sessionAdmin == info) + { + respond(client, info.toString() + " ist bereits Rundenadmin.\n"); + } + sessionAdmin = info; } else { @@ -1266,12 +1339,17 @@ CMD_FUNCTION_IMPL(admin) return; } ClientInfo& interfaceAdmin = *interfaceAdminPtr; - if(ircAdmin != ClientInfo() && userType < Admin) + if(args.isEmpty() && interfaceAdmin == client) + { + respond(client, "Du ist bereits Rundenadmin!\n"); + return; + } + else if((ircAdmin != ClientInfo() || sessionAdmin != ClientInfo()) && userType < Admin) { respond(client, ircAdmin.toString() + (!ircAdmin.nick.isEmpty() && !sessionAdmin.nick.isEmpty() ? " und " : "") + sessionAdmin.toString() + " ist bereits Rundenadmin!\n"); return; } - else if(args == "") + else if(args.isEmpty()) { interfaceAdmin = client; respond(client, client.toString() + " wurde als Rundenadmin eingetragen!\n"); @@ -1293,16 +1371,28 @@ CMD_FUNCTION_IMPL(host) respond(client, "Maximale Warteschlangenlänge von "+settings["UserListLength"]+" erreicht!\n"); else { - if(args == "") - writeToServer("Bitte gib einen Szenarionamen an!\n"); + if(args.trimmed().isEmpty()) + respond(client, "Bitte gib einen Szenarionamen an!\n"); else { - if(scenExists(args)) + ScenarioSettings scen(args, client); + QStringList argList = args.split(' ', QString::KeepEmptyParts); + if(argList.first().trimmed() == "--league") { - userlist << args; - respond(client, "Szenario " + args + " wurde der Warteschlange hinzugefügt.\n"); - if(userlist.length() == 1 && session["userwish"] != "true" && session["running"] != "true") + argList.removeFirst(); + scen.league = true; + scen.name = argList.join(' '); + } + if(scenExists(scen.name)) + { + userlist << scen; + respond(client, "Szenario " + scen.name + " wurde der Warteschlange" + (scen.league ? " mit Liga" : "") + " hinzugefügt.\n"); + if(userlist.length() == 1 && session["userwish"] != "true" && session["running"] != "true" && session["hosting"] == "true") respond(client, "Überrede alle Spieler zu leaven und dein Wunsch wird sofort gehostet ;-)\n"); + else if(session["hosting"] != "true") + { + nextScen(); + } } else { @@ -1373,13 +1463,15 @@ CMD_FUNCTION_IMPL(skip) CMD_FUNCTION_IMPL(next) { - skipCurrent(); - respond(client, "Versuche zu überspringen...\n"); + if(skipCurrent()) + { + respond(client, "Versuche zu überspringen...\n"); + } } CMD_FUNCTION_IMPL(kill) { - serverprocess->kill(); + processManager->kill(); respond(client, "Clonk-Server wurde gekillt.\n"); } @@ -1534,6 +1626,56 @@ CMD_FUNCTION_IMPL(clientlist) respond(client, response + "\n"); } +CMD_FUNCTION_IMPL(set) +{ + QString what = args.left(args.indexOf(QRegExp("\\s"))).trimmed(); + QString newArgs = args.right(args.length() - args.indexOf(QRegExp("\\s"))).trimmed(); + + if(what == "teamcolors" || what == "runtimejoin" || what == "faircrew") + { + if(newArgs != "on" && newArgs != "off") + { + respond(client, what + " kann nur auf on oder off gesetzt werden.\n"); + } + else + { + writeToServer("/set " + what + " " + newArgs + "\n"); + } + } + else if(what == "maxplayer") + { + bool ok; + int max = newArgs.toInt(&ok); + if(!ok) + { + respond(client, "maxplayer muss eine Zahl sein!\n"); + } + else + { + writeToServer("/set maxplayer " + QString::number(max) + "\n"); + } + } + else if(what == "password") + { + writeToServer("/set password " + newArgs + "\n"); + } + else if(what == "comment") + { + if(userType < Moderator) + { + rightsFailMessage(client, Moderator); + } + else + { + writeToServer("/set comment " + newArgs + "\n"); + } + } + else + { + respond(client, "Unbekannte Option: \"" + what + "\"\n"); + } +} + IRC_CHECK_CALLBACK_IMPL(ircSetAdmin) { if(status <= 0) @@ -1549,7 +1691,7 @@ IRC_CHECK_CALLBACK_IMPL(ircSetAdmin) IRC_CHECK_CALLBACK_IMPL(ircModCmd) { - if(status == 3) + if(status == 3 && lists["IrcModerators"].contains(subject.nick)) { ircMods.append(subject.nick); QList<QPair<CmdFunctionRef, QString>> &fifo = ircModFifos[subject.nick]; @@ -1566,7 +1708,10 @@ IRC_CHECK_CALLBACK_IMPL(ircModCmd) } else { - rightsFailMessage(subject, ircModFifos[subject.nick].first().first.userType); - ircModFifos.remove(subject.nick); + if(ircModFifos.contains(subject.nick)) + { + rightsFailMessage(subject, ircModFifos[subject.nick].first().first.userType); + ircModFifos.remove(subject.nick); + } } } |
