summaryrefslogtreecommitdiffstats
path: root/crsm.cpp
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2015-03-18 17:38:51 +0100
committerMarkus Mittendrein <git@maxmitti.tk>2015-03-18 17:38:51 +0100
commit8983d3b38421843db67a05edee180028959c1b51 (patch)
tree904305965e9ba3baa27680d5d8b2a7b8dbea213e /crsm.cpp
parentfbe3c5fbe1327fd81e2eb8fe30a75c4cf5d7b35c (diff)
downloadmanager-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.cpp255
1 files changed, 200 insertions, 55 deletions
diff --git a/crsm.cpp b/crsm.cpp
index 2a4a1b8..69af23b 100644
--- a/crsm.cpp
+++ b/crsm.cpp
@@ -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);
+ }
}
}