summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ClientInfo.hpp23
-rw-r--r--CmdFunctionRef.hpp2
-rw-r--r--CrServerManager.pro4
-rw-r--r--crsm.cpp396
-rw-r--r--crsm.hpp15
5 files changed, 282 insertions, 158 deletions
diff --git a/ClientInfo.hpp b/ClientInfo.hpp
index e2c7864..8099b59 100644
--- a/ClientInfo.hpp
+++ b/ClientInfo.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <QDateTime>
#include <QString>
enum ClientInterface {
@@ -30,6 +31,8 @@ public:
QString pcName = "";
bool activated = false;
+ QList<QDateTime> antiFloodList;
+
QString target = "";
ManagementConnection management;
@@ -52,7 +55,7 @@ public:
ClientInfo ret;
ret.interface = Clonk;
ret.nick = nick;
- ret.nick = pcName;
+ ret.pcName = pcName;
ret.CUID = CUID;
ret.activated = activated;
return ret;
@@ -84,8 +87,26 @@ public:
return !operator==(other);
}
+ inline bool operator<(const ClientInfo& other) const
+ {
+ return toString() < other.toString();
+ }
+
inline QString toString() const
{
return interface == Auto ? "~auto~" : interface == Management ? management.name + " {CLI}" : (!nick.isEmpty() ? nick + (interface == Clonk ? " (" + pcName + ")" : " [IRC]") : "");
}
+
+ inline bool floodCheck(int maxCount, int floodTimeSecs, QDateTime newDateTime = QDateTime::currentDateTime())
+ {
+ foreach(const QDateTime& dateTime, antiFloodList)
+ {
+ if(dateTime.secsTo(newDateTime) > floodTimeSecs)
+ {
+ antiFloodList.removeAll(dateTime);
+ }
+ }
+ antiFloodList.push_back(newDateTime);
+ return antiFloodList.size() > maxCount;
+ }
};
diff --git a/CmdFunctionRef.hpp b/CmdFunctionRef.hpp
index 9c77348..f862823 100644
--- a/CmdFunctionRef.hpp
+++ b/CmdFunctionRef.hpp
@@ -7,7 +7,7 @@
class CRSM;
#define CMD_FUNCTION(name) void name(const QString& cmd, const QString& args, const ClientInfo& client, UserType userType)
-#define CMD_FUNCTION_IMPL(name) void CRSM::name(const QString& cmd, const QString& args, const ClientInfo& client, UserType userType)
+#define CMD_FUNCTION_IMPL(name) void CRSM::name(const QString& cmd, const QString& args, const ClientInfo& client, UserType userType) { (void)cmd; (void)args; (void)client; (void)userType;
enum UserType {
User = 0,
diff --git a/CrServerManager.pro b/CrServerManager.pro
index d41e1c5..5323fea 100644
--- a/CrServerManager.pro
+++ b/CrServerManager.pro
@@ -12,7 +12,7 @@ TARGET = CrServerManager
CONFIG += console
CONFIG -= app_bundle
-include(libcommuni/src/src.pri)
+include(libcommuni/src/core/core.pri)
TEMPLATE = app
@@ -28,4 +28,4 @@ HEADERS += \
ProcessManager.hpp
equals(QT_ARCH, "x86_64"):linux-*: DEFINES += Q_OS_LINUX64
-QMAKE_CXXFLAGS *= -std=c++11
+QMAKE_CXXFLAGS *= -std=c++11 -Wall -Wextra -Werror -Wunused
diff --git a/crsm.cpp b/crsm.cpp
index 4a7c726..9a48058 100644
--- a/crsm.cpp
+++ b/crsm.cpp
@@ -70,8 +70,8 @@ CRSM::CRSM(QObject *parent) :
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()));
+ //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");
reallog->open(QIODevice::Append | QIODevice::Text);
@@ -79,25 +79,7 @@ CRSM::CRSM(QObject *parent) :
if(settings["UseIrc"] == "true")
{
- connection = new IrcConnection(settings["IrcServer"]);
- connection->setUserName(settings["IrcNick"]);
- connection->setNickName(settings["IrcNick"]);
- connection->setRealName(settings["IrcRealName"]);
- connection->sendCommand(IrcCommand::createMode(settings["IrcNick"], "+B"));
- connection->sendCommand(IrcCommand::createJoin(settings["IrcChannel"]));
- if(settings["IrcUseIngameChat"] == "true" && !settings["IrcIngameChannel"].isEmpty())
- {
- connection->sendCommand(IrcCommand::createJoin(settings["IrcIngameChannel"]));
- connection->sendCommand(IrcCommand::createTopic(settings["IrcIngameChannel"], "Kein laufendes Spiel."));
- }
- else
- {
- settings["IrcUseIngameChat"] = "false";
- }
-
- connection->setPassword(settings["IrcPassword"]);
- connect(connection, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(ircMessageReceived(IrcMessage*)));
- connection->open();
+ prepareAndConnectIrc();
}
else
{
@@ -124,7 +106,7 @@ bool CRSM::isOk()
void CRSM::readServerOutput()
{
- static QRegExp timeRemover("^>?\\s*\\[\\d\\d:\\d\\d:\\d\\d\\]\\s+(.*)$");
+ static QRegExp timeRemover("^>?\\s*\\[(\\d\\d:\\d\\d:\\d\\d)\\]\\s+(.*)$");
QString what(processManager->readLine());
if(settings["ServerUsesReadline"] == "true")
@@ -155,32 +137,40 @@ void CRSM::readServerOutput()
out(what.trimmed() + "\n");
if(!timeRemover.exactMatch(what))
return;
- what = timeRemover.cap(1).trimmed();
+ what = timeRemover.cap(2).trimmed();
- static QRegExp userexp("^\\s*<(.*)\\|(\\d+)\\|([^>]*)>\\s+(.*)$");
+ static QRegExp userexp("^\\s*(\\*?)\\s*<(.*)\\|(\\d+)\\|([^>]*)>\\s+(.*)$");
if(userexp.exactMatch(what))
{
- QString user = userexp.cap(3);
- QString pcName = userexp.cap(1);
- //QString cuid = userexp.cap(2);
- const ClientInfo& info = clients.value(pcName);
- if(user != settings["ServerNick"])
+ bool isMeMessage = (userexp.cap(1) == "*");
+ QString user = userexp.cap(4);
+ QString pcName = userexp.cap(2);
+ int cuid = userexp.cap(3).toInt();
+ if(pcName != settings["ServerPCName"])
{
- QString msg = userexp.cap(4).trimmed();
- QRegExp commandExp("^\\" CMD_SIGN "([^ ]+)(\\s+(.*)\\s*)?$");
- if(commandExp.exactMatch(msg))
+ ClientInfo& info = getClientInfo(pcName, cuid, user);
+ if(info.floodCheck(settings["AntiFloodCount"].toInt(), settings["AntiFloodTime"].toInt(), QDateTime(QDate::currentDate(), QTime::fromString(timeRemover.cap(1), "hh:mm:ss"))))
{
- QString command = commandExp.cap(1).trimmed();
- QString commandArgs = commandExp.cap(2).trimmed();
- if(!cmd(command, commandArgs, info))
- {
- respond(info, "Unbekannter Befehl: \"" + command + "\"!\n");
- }
-
+ kick(pcName, "Flooding! Maximal " + settings["AntiFloodCount"] + " Nachrichten in " + settings["AntiFloodTime"] + "s");
}
- else if(session["IrcUseIngameChat"] == "true")
+ else if(!isMeMessage)
{
- connection->sendCommand(IrcCommand::createMessage(settings["IrcIngameChannel"], "[Clonk]<" + user + "> " + msg));
+ QString msg = userexp.cap(5).trimmed();
+ QRegExp commandExp("^\\" CMD_SIGN "([^ ]+)(\\s+(.*)\\s*)?$");
+ if(commandExp.exactMatch(msg))
+ {
+ QString command = commandExp.cap(1).trimmed();
+ QString commandArgs = commandExp.cap(2).trimmed();
+ if(!cmd(command, commandArgs, info))
+ {
+ respond(info, "Unbekannter Befehl: \"" + command + "\"!\n");
+ }
+
+ }
+ else if(session["IrcUseIngameChat"] == "true")
+ {
+ connection->sendCommand(IrcCommand::createMessage(settings["IrcIngameChannel"], "[Clonk]<" + user + "> " + msg));
+ }
}
}
}
@@ -190,17 +180,17 @@ void CRSM::readServerOutput()
static QRegExp infoMatch("^<(.*)\\|(\\d+)\\|(.*)>$");
if(infoMatch.exactMatch(joinExp.cap(1)))
{
- ClientInfo info;
- info.CUID = infoMatch.cap(2).toInt();
- info.nick = infoMatch.cap(3);
- info.pcName = infoMatch.cap(1);
- info.interface = Clonk;
+ const ClientInfo& info = ClientInfo::clonkClient(infoMatch.cap(3), infoMatch.cap(1), infoMatch.cap(2).toInt());
clients.insert(info.pcName, info);
QTimer *timer = new QTimer;
connect(timer, SIGNAL(timeout()), &greetMapper, SLOT(map()));
connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
greetMapper.setMapping(timer, info.pcName);
- timer->start(500);
+ timer->start(1000);
+ if(session["IrcUseIngameChat"] == "true")
+ {
+ connection->sendCommand(IrcCommand::createMessage(settings["IrcIngameChannel"], "[Clonk] " + info.toString() + " verbunden."));
+ }
}
}
@@ -210,7 +200,7 @@ void CRSM::readServerOutput()
QRegExp infoMatch("^<(.*)\\|(\\d+)\\|(.*)>$");
if(infoMatch.exactMatch(joinExp.cap(1)))
{
- ClientInfo &info = clients[infoMatch.cap(1)];
+ ClientInfo &info = getClientInfo(infoMatch.cap(1), infoMatch.cap(2).toInt(), infoMatch.cap(3));
info.activated = true;
}
}
@@ -221,7 +211,7 @@ void CRSM::readServerOutput()
QRegExp infoMatch("^<(.*)\\|(\\d+)\\|(.*)>$");
if(infoMatch.exactMatch(joinExp.cap(1)))
{
- ClientInfo &info = clients[infoMatch.cap(1)];
+ ClientInfo &info = getClientInfo(infoMatch.cap(1), infoMatch.cap(2).toInt(), infoMatch.cap(3));
info.activated = false;
}
}
@@ -243,8 +233,21 @@ void CRSM::readServerOutput()
QRegExp infoMatch("^<(.*)\\|(\\d+)\\|(.*)>$");
if(infoMatch.exactMatch(leaveExp.cap(1)))
{
- ClientInfo &info = clients[infoMatch.cap(1)];
+ ClientInfo &info = getClientInfo(infoMatch.cap(1), infoMatch.cap(2).toInt(), infoMatch.cap(3));
writeToServer(QString(info.nick +" ist ein L34V0R!\n"));
+
+ if(session["IrcUseIngameChat"] == "true")
+ {
+ connection->sendCommand(IrcCommand::createMessage(settings["IrcIngameChannel"], "[Clonk] " + info.toString() + " entfernt" + leaveExp.cap(2)));
+ }
+
+ if(info == sessionAdmin)
+ {
+ leaveAdmins.insert(info, QDateTime::currentDateTime());
+ writeToServer("Rundenadmin wurde freigegeben.\n");
+ sessionAdmin = ClientInfo();
+ }
+
clients.remove(info.pcName);
}
if(clients.size() == 0 && userlist.length() > 0 && session["userwish"] != "true")
@@ -392,7 +395,7 @@ void CRSM::scenarioFinished()
sessionAdmin = ClientInfo();
ircAdmin = ClientInfo();
clients.clear();
- greeted.clear();
+ leaveAdmins.clear();
if((autoHost || userlist.length() > 0) && !finish)
nextScen();
else if(!settings["IrcIngameChannel"].isEmpty())
@@ -503,6 +506,10 @@ void CRSM::ircMessageReceived(IrcMessage *message)
{
stopAliasWishEditing();
}
+ if(ircAdmin == ClientInfo::ircClient(message->nick()))
+ {
+ ircAdmin = ClientInfo();
+ }
}
else if(message->type() == IrcMessage::Kick)
{
@@ -545,6 +552,18 @@ void CRSM::greet(QString pcName)
return;
const ClientInfo &info = clients.value(pcName);
writeToServer(QString("Hallo " + info.nick + "!\n"));
+ if(leaveAdmins.contains(info))
+ {
+ int timeGone;
+ if((timeGone = leaveAdmins.value(info).secsTo(QDateTime::currentDateTime())) < settings["RegainAdminTime"].toInt() && sessionAdmin != ClientInfo())
+ {
+ writeToServer(info.nick + "! Der Rundenadmin wurde freigegeben, weil du das Spiel verlassen hast.\nDu hast noch " + QString::number(settings["RegainAdminTime"].toInt() - timeGone) + "s Zeit um den Rundenadmin zurückzuholen.\n");
+ }
+ else
+ {
+ leaveAdmins.remove(info);
+ }
+ }
}
void CRSM::newManagementConnection()
@@ -609,6 +628,7 @@ void CRSM::newManagementData()
void CRSM::managementConnectionDisconnected()
{
QTcpSocket* sock = (QTcpSocket*)sender();
+ out(managementConnections.value(sock).name + "disconnected from Management-Interface.");
if(managementConnections.contains(sock))
{
managementConnections.remove(sock);
@@ -682,20 +702,26 @@ void CRSM::readConfig()
{
lists.clear();
settings.clear();
+ settings["IrcReconnectDelay"] = "10";
settings["EmptyTimer"] = "60";
settings["MaxUserWishes"] = "2";
settings["MaxScenWishes"] = "2";
+ settings["AntiFloodCount"] = "5";
+ settings["AntiFloodTime"] = "3";
+ settings["RegainAdminTime"] = "120";
+ settings["ServerExecutable"] = "clonk-server";
+ settings["Arguments"] = "/fullscreen /lobby:300 /nosignup Objects.c4d";
+ settings["ClonkConfig"] = "config";
+ settings["UserListLength"] ="5";
+ settings["ManagementPort"] = "9372";
+
QFile config(CONFIG_FILE_NAME);
- if(!config.exists() || !config.open(QIODevice::ReadOnly | QIODevice::Text))
+ if(!config.exists())
{
config.open(QIODevice::WriteOnly | QIODevice::Text);
- settings = defaultSettings();
- foreach(const QString &key, settings.keys())
- {
- config.write(QString(key+" = "+settings.value(key)+"\n").toUtf8());
- }
+ writeConfig();
}
- else
+ else if(config.open(QIODevice::ReadOnly | QIODevice::Text))
{
QRegExp confExp("^([^=]+)=(.*)$");
QRegExp confPlusExp("^([^=]+)\\+=(.*)$");
@@ -719,34 +745,34 @@ void CRSM::readConfig()
if(config.atEnd())
break;
}
+ }
- out("config:\n");
- foreach(const QString &key, settings.keys())
- {
- out(key + " = " + settings.value(key) + "\n");
- }
- out("\n");
- foreach(const QString &key, lists.keys())
+ out("config:\n");
+ foreach(const QString &key, settings.keys())
+ {
+ out(key + " = " + settings.value(key) + "\n");
+ }
+ out("\n");
+ foreach(const QString &key, lists.keys())
+ {
+ out(key + ":\n");
+ foreach(const QString &val, lists.value(key))
{
- out(key + ":\n");
- foreach(const QString &val, lists.value(key))
- {
- out("\t" + val + "\n");
- }
+ out("\t" + val + "\n");
}
- out("\n");
- foreach(const QString &key, maps.keys())
+ }
+ out("\n");
+ foreach(const QString &key, maps.keys())
+ {
+ out(key + ":\n");
+ foreach(const QString &mapkey, maps.value(key).keys())
{
- out(key + ":\n");
- foreach(const QString &mapkey, maps.value(key).keys())
- {
- out("\t[" + mapkey + "]" + " = " + maps.value(key).value(mapkey) + "\n");
- }
+ out("\t[" + mapkey + "]" + " = " + maps.value(key).value(mapkey) + "\n");
}
- out("\n");
- args = settings["Arguments"].split(" ");
- args << "/config:"+settings["ClonkConfig"];
}
+ out("\n");
+ args = settings["Arguments"].split(" ");
+ args << "/config:"+settings["ClonkConfig"];
settings["ClonkDirectory"] = QFileInfo(settings["ServerExecutable"]).absoluteDir().absolutePath()+QDir::separator();
QFile clonkconfig(settings["ClonkConfig"]);
@@ -816,14 +842,15 @@ void CRSM::readScenarios()
scen.randomLeague = true;
scen.name = argList.join(' ');
}
- if(scenExists(scen.name))
+ QString scenName = scen.name;
+ if(!(scen.name = scenPath(scen.name)).isEmpty())
{
out(scen.name + "\n");
autolist.append(scen);
}
else
{
- out("WARNING: Scenario " + scen.name + " not found!\n");
+ out("WARNING: Scenario " + scenName + " not found!\n");
}
}
@@ -833,16 +860,6 @@ void CRSM::readScenarios()
updateNextAutoScens();
}
-QMap<QString, QString> CRSM::defaultSettings()
-{
- QMap<QString, QString> temp;
- temp.insert("ServerExecutable","clonk-server");
- temp.insert("Arguments","/fullscreen /lobby:60 /nosignup");
- temp.insert("ClonkConfig","config");
- temp.insert("UserListLength","5");
- return temp;
-}
-
void CRSM::listC4Folders()
{
out("Listing Contents of C4Folders...");
@@ -878,33 +895,73 @@ void CRSM::cleanUp()
out("\n");
}
-bool CRSM::scenExists(QString filePath)
+QString CRSM::scenPath(QString scenName)
{
- while(maps["Alias"].contains(filePath))
- filePath = maps["Alias"].value(filePath);
- QFileInfo fileInfo(settings["ClonkDirectory"]+filePath);
+ bool isAlias = false;
+ QString aliasName;
+ foreach(const QString& alias, maps["Alias"].keys())
+ {
+ if(alias.compare(scenName, Qt::CaseInsensitive) == 0)
+ {
+ aliasName = scenName = alias;
+ break;
+ }
+ }
+ while(maps["Alias"].contains(scenName))
+ {
+ scenName = maps["Alias"].value(scenName);
+ isAlias = true;
+ }
+ QFileInfo fileInfo(settings["ClonkDirectory"] + scenName);
if(fileInfo.suffix() != "c4s")
- return false;
+ {
+ return QString();
+ }
bool exists = fileInfo.exists();
- if(!exists)
+ if(exists && isAlias)
+ {
+ return aliasName;
+ }
+ if(exists)
{
- QStringList split = filePath.split('/');
- QString name = filePath.right(filePath.length() - split.first().length() - 1);
+ return scenName;
+ }
+ else
+ {
+ QStringList split = scenName.split('/');
+ QString name = scenName.right(scenName.length() - split.first().length() - 1);
if(split.length() >= 2)
{
if(split.first().right(4) == ".c4f")
{
- QFile lstFile(settings["ClonkDirectory"] + split.first() + ".lst");
+ const QStringList& entryList = QDir(settings["ClonkDirectory"]).entryList(QStringList() << "*.c4f");
+ QString folderName = split.first();
+ foreach(const QString& entry, entryList)
+ {
+ if(entry.compare(folderName, Qt::CaseInsensitive) == 0)
+ {
+ folderName = entry;
+ break;
+ }
+ }
+ QFile lstFile(settings["ClonkDirectory"] + folderName + ".lst");
if(lstFile.exists())
{
lstFile.open(QFile::ReadOnly);
while(!lstFile.atEnd())
{
- QString line = lstFile.readLine().trimmed();
- if(line == name)
+ const QString& line = lstFile.readLine().trimmed();
+ if(line.compare(name, Qt::CaseInsensitive) == 0)
{
- exists = true;
- break;
+ lstFile.close();
+ if(isAlias)
+ {
+ return aliasName;
+ }
+ else
+ {
+ return folderName + '/' + line;
+ }
}
}
}
@@ -912,7 +969,7 @@ bool CRSM::scenExists(QString filePath)
}
}
}
- return exists;
+ return QString();
}
QString CRSM::listScenarios(QString commandArgs)
@@ -1103,21 +1160,30 @@ QString CRSM::addAliasWish(const QString &param)
{
const QString &alias = aliasExp.cap(1).trimmed();
const QString &scen = aliasExp.cap(2).trimmed();
+ QString scenP = scen;
if(maps["Alias"].contains(alias))
+ {
return "Alias ist bereits vergeben!";
+ }
else if(maps["AliasWishes"].contains(alias))
+ {
return "Alias ist bereits als Wunsch vergeben!";
- else if(scenExists(scen))
+ }
+ else if(!(scenP = scenPath(scen)).isEmpty())
{
- maps["AliasWishes"].insert(alias, scen);
+ maps["AliasWishes"].insert(alias, scenP);
informModsAboutAliasWish();
return "Aliaswunsch ist hinterlegt!";
}
else
+ {
return "Szenario \"" + scen + "\" wurde nicht gefunden!";
+ }
}
else
+ {
return "Eingabefehler! Siehe !help für mehr Informationen.";
+ }
}
void CRSM::informModsAboutAliasWish()
@@ -1379,6 +1445,7 @@ void CRSM::setupCmds()
addCommand("exitafter", &CRSM::exitAfter, Management, UserType::Max, "Beendet den Server-Manager, sobald das laufende Spiel vorbei ist.");
addCommand("reload", &CRSM::reload, Management, UserType::Max, "Liest die Konfigurationsdatei neu ein.");
addCommand("saveconfig", &CRSM::saveConfig, Management, UserType::Max, "Speichert die aktuelle Konfiguration in die Konfigurationsdatei.");
+ addCommand("reconnectirc", &CRSM::reconnectIrc, Management, UserType::Max, "Stellt die IRC-Verbindung wieder her.");
}
void CRSM::respond(const ClientInfo &client, const QString &message, const RespondType type)
@@ -1532,11 +1599,49 @@ bool CRSM::scenAllowed(const ScenarioSettings &scen, const ClientInfo &client, U
respond(client, "Von dir sind jetzt genug Wünsche in der Liste!\n");
return false;
}
+ return true;
}
-CMD_FUNCTION_IMPL(help)
+void CRSM::kick(const QString& pcName, const QString& reason)
+{
+ writeToServer("/kick " + pcName + (reason.isEmpty() ? QString("") : QString(" ") + reason) + "\n");
+}
+
+void CRSM::prepareAndConnectIrc()
+{
+ connection = new IrcConnection(settings["IrcServer"]);
+ connection->setUserName(settings["IrcNick"]);
+ connection->setNickName(settings["IrcNick"]);
+ connection->setRealName(settings["IrcRealName"]);
+ connection->setReconnectDelay(settings["IrcReconnectDelay"].toInt());
+ connection->sendCommand(IrcCommand::createMode(settings["IrcNick"], "+B"));
+ connection->sendCommand(IrcCommand::createJoin(settings["IrcChannel"]));
+ if(settings["IrcUseIngameChat"] == "true" && !settings["IrcIngameChannel"].isEmpty())
+ {
+ connection->sendCommand(IrcCommand::createJoin(settings["IrcIngameChannel"]));
+ connection->sendCommand(IrcCommand::createTopic(settings["IrcIngameChannel"], "Kein laufendes Spiel."));
+ }
+ else
+ {
+ settings["IrcUseIngameChat"] = "false";
+ }
+
+ connection->setPassword(settings["IrcPassword"]);
+ connect(connection, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(ircMessageReceived(IrcMessage*)));
+ connection->open();
+}
+
+ClientInfo &CRSM::getClientInfo(const QString &pcName, int cuid, const QString &user)
{
- bool longHelp = args == "long";
+ if(!clients.contains(pcName))
+ {
+ clients.insert(pcName, ClientInfo::clonkClient(user, pcName, cuid));
+ }
+ return clients[pcName];
+}
+
+CMD_FUNCTION_IMPL(help)
+ bool longHelp = (args == "long");
if(args.isEmpty() || longHelp)
{
QString response = "Verfügbare Befehle: ";
@@ -1574,12 +1679,10 @@ CMD_FUNCTION_IMPL(help)
}
CMD_FUNCTION_IMPL(passToClonk)
-{
writeToServer('/' + cmd + ' ' + args + '\n');
}
CMD_FUNCTION_IMPL(admin)
-{
ClientInfo *interfaceAdminPtr;
switch(client.interface)
{
@@ -1603,7 +1706,7 @@ CMD_FUNCTION_IMPL(admin)
respond(client, "Du ist bereits Rundenadmin!\n");
return;
}
- else if((ircAdmin != ClientInfo() || sessionAdmin != ClientInfo()) && userType < Admin)
+ else if((ircAdmin != ClientInfo() || sessionAdmin != ClientInfo()) && userType < Admin && !(leaveAdmins.contains(client) && leaveAdmins.value(client).secsTo(QDateTime::currentDateTime()) < settings["RegainAdminTime"].toInt()))
{
respond(client, ircAdmin.toString() + (!ircAdmin.nick.isEmpty() && !sessionAdmin.nick.isEmpty() ? " und " : "") + sessionAdmin.toString() + " ist bereits Rundenadmin!\n");
return;
@@ -1625,7 +1728,6 @@ CMD_FUNCTION_IMPL(admin)
}
CMD_FUNCTION_IMPL(host)
-{
if(userlist.length() >= settings["UserListLength"].toInt())
respond(client, "Maximale Warteschlangenlänge von "+settings["UserListLength"]+" erreicht!\n");
else
@@ -1642,7 +1744,7 @@ CMD_FUNCTION_IMPL(host)
scen.league = true;
scen.name = argList.join(' ');
}
- if(scenExists(scen.name))
+ if(!(scen.name = scenPath(scen.name)).isEmpty())
{
if(scenAllowed(scen, client, userType))
{
@@ -1654,7 +1756,7 @@ CMD_FUNCTION_IMPL(host)
{
nextScen();
}
- else if(clients.size() == 0)
+ else if(clients.size() == 0 && session["userwish"] != "true")
{
processManager->closeProgFifos();
}
@@ -1669,8 +1771,7 @@ CMD_FUNCTION_IMPL(host)
}
CMD_FUNCTION_IMPL(list)
-{
- if(client.interface == Clonk)
+ if(client.interface == Clonk || client.interface == Management)
{
respond(client, listScenarios(args));
}
@@ -1681,22 +1782,18 @@ CMD_FUNCTION_IMPL(list)
}
CMD_FUNCTION_IMPL(queue)
-{
- respond(client, printQueue(), RespondType::Notice);
+ respond(client, printQueue(), RespondType::PrivateNotice);
}
CMD_FUNCTION_IMPL(aliaswish)
-{
respond(client, addAliasWish(args) + "\n");
}
CMD_FUNCTION_IMPL(ircchat)
-{
respond(client, ircActivateIngameChat(args.toLower() == "on") + "\n");
}
CMD_FUNCTION_IMPL(autohost)
-{
if(cmd == "autohost")
{
autoHost = true;
@@ -1715,7 +1812,6 @@ CMD_FUNCTION_IMPL(autohost)
}
CMD_FUNCTION_IMPL(skip)
-{
QString skipped;
if((skipped = skipScen()) != "")
{
@@ -1728,7 +1824,6 @@ CMD_FUNCTION_IMPL(skip)
}
CMD_FUNCTION_IMPL(next)
-{
if(skipCurrent())
{
respond(client, "Versuche zu überspringen...\n");
@@ -1736,13 +1831,11 @@ CMD_FUNCTION_IMPL(next)
}
CMD_FUNCTION_IMPL(kill)
-{
processManager->kill();
respond(client, "Clonk-Server wurde gekillt.\n");
}
CMD_FUNCTION_IMPL(clear)
-{
if(userlist.length() > 0)
{
userlist.clear();
@@ -1755,7 +1848,6 @@ CMD_FUNCTION_IMPL(clear)
}
CMD_FUNCTION_IMPL(aliaswishes)
-{
if(aliasWishEditor == "")
{
aliasWishEditor = client.nick;
@@ -1768,13 +1860,13 @@ CMD_FUNCTION_IMPL(aliaswishes)
}
CMD_FUNCTION_IMPL(newalias)
-{
QRegExp aliasExp("^([^=]+)=(.*)$");
if(aliasExp.exactMatch(args))
{
const QString &scen = aliasExp.cap(2).trimmed();
const QString &alias = aliasExp.cap(1).trimmed();
- if(scenExists(scen))
+ QString scenP = scen;
+ if(!(scenP = scenPath(scen)).isEmpty())
{
if(maps["AliasWishes"].contains(alias))
{
@@ -1789,17 +1881,20 @@ CMD_FUNCTION_IMPL(newalias)
{
respond(client, "Alias hinzugefügt!\n");
}
- maps["Alias"][alias] = scen;
+ maps["Alias"][alias] = scenP;
}
else
+ {
respond(client, "Szenario \"" + scen + "\" wurde nicht gefunden!\n");
+ }
}
else
+ {
respond(client, "Eingabefehler! Siehe !help newalias für mehr Informationen.\n");
+ }
}
CMD_FUNCTION_IMPL(modinfo)
-{
respond(client, "Moderatoren sind (* ist aktiv, + verwendet IO):\n", RespondType::Private);
foreach(const QString &mod, lists["IrcModerators"])
{
@@ -1808,7 +1903,6 @@ CMD_FUNCTION_IMPL(modinfo)
}
CMD_FUNCTION_IMPL(io)
-{
if(ircModIOList.contains(client.nick))
ircModIOList.removeAll(client.nick);
else
@@ -1816,7 +1910,6 @@ CMD_FUNCTION_IMPL(io)
}
CMD_FUNCTION_IMPL(pcNamePassToClonk)
-{
ClientInfo info;
if(clients.contains(args))
{
@@ -1824,11 +1917,22 @@ CMD_FUNCTION_IMPL(pcNamePassToClonk)
}
else
{
+ foreach(const QString& pcName, clients.keys())
+ {
+ if(pcName.compare(args, Qt::CaseInsensitive) == 0)
+ {
+ info = clients.value(pcName);
+ break;
+ }
+ }
+ }
+ if(info == ClientInfo())
+ {
bool notFound = true, ambigous = false;
ClientInfo foundClient;
foreach(const ClientInfo& client, clients)
{
- if(client.nick == args)
+ if(client.nick.compare(args, Qt::CaseInsensitive) == 0)
{
if(!notFound)
{
@@ -1863,24 +1967,20 @@ CMD_FUNCTION_IMPL(pcNamePassToClonk)
}
CMD_FUNCTION_IMPL(ircadmin)
-{
ircCheckUserStatus(client, ClientInfo::ircClient(args), &CRSM::ircSetAdmin);
}
CMD_FUNCTION_IMPL(ingameadmin)
-{
setIngameAdmin(client, args);
}
CMD_FUNCTION_IMPL(noadmin)
-{
ircAdmin = ClientInfo();
sessionAdmin = ClientInfo();
respond(client, "Rundenadmin wurde freigegeben.\n");
}
CMD_FUNCTION_IMPL(clientlist)
-{
QString response = "Verbundene Clients (Chatnick (PC-Name)): ";
foreach(const ClientInfo& connectedClient, clients)
{
@@ -1893,7 +1993,6 @@ CMD_FUNCTION_IMPL(clientlist)
}
CMD_FUNCTION_IMPL(set)
-{
QString what = args.left(args.indexOf(QRegExp("\\s"))).trimmed();
QString newArgs = args.right(args.length() - args.indexOf(QRegExp("\\s"))).trimmed();
@@ -1943,7 +2042,6 @@ CMD_FUNCTION_IMPL(set)
}
CMD_FUNCTION_IMPL(join)
-{
QStringList argList = args.split(' ');
static QRegExp chanExp("^#[^\\s]+$");
if(argList.size() < 1 || argList.first().isEmpty())
@@ -1963,7 +2061,6 @@ CMD_FUNCTION_IMPL(join)
}
CMD_FUNCTION_IMPL(leave)
-{
QStringList argList = args.split(' ');
QString chan, reason;
if(!argList.isEmpty())
@@ -1992,7 +2089,6 @@ CMD_FUNCTION_IMPL(leave)
}
CMD_FUNCTION_IMPL(exit)
-{
processManager->closeProgFifos();
settings.remove("ReattachId");
finish = true;
@@ -2001,20 +2097,17 @@ CMD_FUNCTION_IMPL(exit)
}
CMD_FUNCTION_IMPL(exitDetach)
-{
settings["ReattachId"] = processManager->ID();
writeConfig();
QCoreApplication::quit();
}
CMD_FUNCTION_IMPL(exitUpdate)
-{
writeToServer("Der Server Manager wird upgedatet. Befehle funktionieren temporär nicht.\n");
exitDetach(cmd, args, client, userType);
}
CMD_FUNCTION_IMPL(exitAfter)
-{
if(processManager->isRunning())
{
finish = true;
@@ -2028,7 +2121,6 @@ CMD_FUNCTION_IMPL(exitAfter)
}
CMD_FUNCTION_IMPL(reload)
-{
out("Reloading configuration...");
ircModChecks.clear();
ircMods.clear();
@@ -2041,14 +2133,19 @@ CMD_FUNCTION_IMPL(reload)
}
CMD_FUNCTION_IMPL(saveConfig)
-{
out("Saving Configuration...");
writeConfig();
out("Configuration saved.");
}
+CMD_FUNCTION_IMPL(reconnectIrc)
+ respond(client, "Reconnecting...\n");
+ connection->close();
+ delete connection;
+ prepareAndConnectIrc();
+}
+
IRC_CHECK_CALLBACK_IMPL(ircSetAdmin)
-{
if(status <= 0)
{
respond(requester, "IRC-Nutzer " + subject.toString() + " wurde nicht gefunden!\n");
@@ -2061,7 +2158,6 @@ IRC_CHECK_CALLBACK_IMPL(ircSetAdmin)
}
IRC_CHECK_CALLBACK_IMPL(ircModCmd)
-{
if(status == 3 && lists["IrcModerators"].contains(subject.nick))
{
ircMods.append(subject.nick);
diff --git a/crsm.hpp b/crsm.hpp
index b353950..d96cc7b 100644
--- a/crsm.hpp
+++ b/crsm.hpp
@@ -27,7 +27,7 @@
#define SCOREBOARD_FILE_NAME settings["ClonkDirectory"] + "scoreboard.html"
#define IRC_CHECK_CALLBACK(name) void name(const ClientInfo& requester, int status, const ClientInfo& subject)
-#define IRC_CHECK_CALLBACK_IMPL(name) void CRSM::name(const ClientInfo& requester, int status, const ClientInfo& subject)
+#define IRC_CHECK_CALLBACK_IMPL(name) void CRSM::name(const ClientInfo& requester, int status, const ClientInfo& subject) { (void)requester; (void)status; (void)subject;
#ifdef Q_OS_LINUX64
#define C4GROUP_EXECUTABLE "c4group64"
@@ -120,7 +120,6 @@ private:
QMap<QString, QString> settings;
QMap<QString, QString> session;
QMap<QString, ClientInfo> clients;
- QStringList greeted;
QMap<QString, QStringList> lists;
QMap<QString, QMap<QString, QString>> maps;
IrcConnection *connection = 0;
@@ -128,6 +127,7 @@ private:
QSignalMapper greetMapper;
ClientInfo sessionAdmin;
ClientInfo ircAdmin;
+ QMap<ClientInfo, QDateTime> leaveAdmins;
QFile *logfile;
QTextStream logstream;
QTextCodec *codec;
@@ -143,10 +143,9 @@ private:
void startScen(const ScenarioSettings& scen, QStringList);
void readConfig();
void readScenarios();
- QMap<QString, QString> defaultSettings();
void listC4Folders();
void cleanUp();
- bool scenExists(QString filePath);
+ QString scenPath(QString scenName);
QString listScenarios(QString commandArgs);
QString printQueue();
void ircCheckModCmd(const QString &nick, CmdFunctionRef func, QString arg = "");
@@ -180,6 +179,12 @@ private:
bool scenAllowed(const ScenarioSettings& scen, const ClientInfo& client, UserType userType);
+ void kick(const QString& pcName, const QString& reason = "");
+
+ void prepareAndConnectIrc();
+
+ ClientInfo& getClientInfo(const QString& pcName, int cuid, const QString& user);
+
CMD_FUNCTION(help);
CMD_FUNCTION(passToClonk);
CMD_FUNCTION(admin);
@@ -214,6 +219,8 @@ private:
CMD_FUNCTION(reload);
CMD_FUNCTION(saveConfig);
+ CMD_FUNCTION(reconnectIrc);
+
IRC_CHECK_CALLBACK(ircSetAdmin);
IRC_CHECK_CALLBACK(ircModCmd);
};