do not get stuck on "in game..." page just because of game crash. output a message instead. could still need some tweaking, but a man gotta sleep. and sheep too...
authorsheepluva
Sun, 15 Jun 2014 04:33:54 +0200
changeset 10307 e13d3147f15b
parent 10306 4fca8bcfaff0
child 10308 7350be35b335
do not get stuck on "in game..." page just because of game crash. output a message instead. could still need some tweaking, but a man gotta sleep. and sheep too...
QTfrontend/game.cpp
QTfrontend/hwform.cpp
QTfrontend/hwform.h
QTfrontend/net/tcpBase.cpp
QTfrontend/net/tcpBase.h
QTfrontend/util/MessageDialog.cpp
hedgewars/uConsts.pas
hedgewars/uIO.pas
--- a/QTfrontend/game.cpp	Sun Jun 15 00:02:25 2014 +0200
+++ b/QTfrontend/game.cpp	Sun Jun 15 04:33:54 2014 +0200
@@ -248,7 +248,12 @@
         case 'E':
         {
             int size = msg.size();
-            emit ErrorMessage(QString("Last two engine messages:\n") + QString().append(msg.mid(2)).left(size - 4));
+            emit ErrorMessage(
+                QString("A Fatal ERROR occured! - The game engine had to stop.")
+                + "\n\n " + tr("We are very sorry for the inconvenience :(")
+                + "\n\n" + tr("If this keeps happening, please click the '%1' button in the main menu!")
+                .arg("Feedback") + "\n\n"
+                "Last two engine messages:\n" + QString().append(msg.mid(2)).left(size - 4));
             return;
         }
         case 'i':
--- a/QTfrontend/hwform.cpp	Sun Jun 15 00:02:25 2014 +0200
+++ b/QTfrontend/hwform.cpp	Sun Jun 15 04:33:54 2014 +0200
@@ -1675,7 +1675,7 @@
     connect(game, SIGNAL(CampStateChanged(int)), this, SLOT(UpdateCampaignPageProgress(int)));
     connect(game, SIGNAL(GameStateChanged(GameState)), this, SLOT(GameStateChanged(GameState)));
     connect(game, SIGNAL(GameStats(char, const QString &)), ui.pageGameStats, SLOT(GameStats(char, const QString &)));
-    connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowErrorMessage(const QString &)), Qt::QueuedConnection);
+    connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowFatalErrorMessage(const QString &)), Qt::QueuedConnection);
     connect(game, SIGNAL(HaveRecord(RecordType, const QByteArray &)), this, SLOT(GetRecord(RecordType, const QByteArray &)));
     m_lastDemo = QByteArray();
 }
@@ -2094,9 +2094,9 @@
     }
 }
 
-void HWForm::ShowErrorMessage(const QString & msg)
+void HWForm::ShowFatalErrorMessage(const QString & msg)
 {
-    MessageDialog::ShowErrorMessage(msg, this);
+    MessageDialog::ShowFatalMessage(msg, this);
 }
 
 void HWForm::showFeedbackDialog()
--- a/QTfrontend/hwform.h	Sun Jun 15 00:02:25 2014 +0200
+++ b/QTfrontend/hwform.h	Sun Jun 15 04:33:54 2014 +0200
@@ -120,7 +120,7 @@
         void StartMPGame();
         void GameStateChanged(GameState gameState);
         void ForcedDisconnect(const QString & reason);
-        void ShowErrorMessage(const QString &);
+        void ShowFatalErrorMessage(const QString &);
         void GetRecord(RecordType type, const QByteArray & record);
         void CreateNetGame();
         void UpdateWeapons();
--- a/QTfrontend/net/tcpBase.cpp	Sun Jun 15 00:02:25 2014 +0200
+++ b/QTfrontend/net/tcpBase.cpp	Sun Jun 15 04:33:54 2014 +0200
@@ -172,7 +172,10 @@
     thread->start();
 #else
     process = new QProcess(this);
-    connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError)));
+    connect(process, SIGNAL(error(QProcess::ProcessError)),
+        this, SLOT(StartProcessError(QProcess::ProcessError)));
+    connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
+        this, SLOT(onEngineDeath(int, QProcess::ExitStatus)));
     QStringList arguments = getArguments();
 
 #ifdef QT_DEBUG
@@ -198,7 +201,9 @@
 #endif
         emit isReadyNow();
     }
+
     IPCSocket->deleteLater();
+    IPCSocket = NULL;
 
     deleteLater();
 }
@@ -217,6 +222,37 @@
     ClientDisconnect();
 }
 
+void TCPBase::onEngineDeath(int exitCode, QProcess::ExitStatus exitStatus)
+{
+    Q_UNUSED(exitStatus);
+
+    ClientDisconnect();
+
+    // show error message if there was an error that was not an engine's
+    // fatal error - because that one already sent a info via IPC
+    if ((exitCode != 0) && (exitCode != 2))
+    {
+        // inform user that something bad happened
+        MessageDialog::ShowFatalMessage(
+            tr("The game engine died unexpectedly!")
+            + QString("\n(exit code %1)").arg(exitCode)
+            + "\n\n " + tr("We are very sorry for the inconvenience :(") + "\n\n" +
+            tr("If this keeps happening, please click the '%1' button in the main menu!")
+            .arg("Feedback"));
+
+    }
+
+    // cleanup up
+    if (IPCSocket)
+    {
+        IPCSocket->close();
+        IPCSocket->deleteLater();
+    }
+
+    // plot suicide
+    deleteLater();
+}
+
 void TCPBase::tcpServerReady()
 {
     disconnect(srvsList.first(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
--- a/QTfrontend/net/tcpBase.h	Sun Jun 15 00:02:25 2014 +0200
+++ b/QTfrontend/net/tcpBase.h	Sun Jun 15 04:33:54 2014 +0200
@@ -88,6 +88,7 @@
         void ClientDisconnect();
         void ClientRead();
         void StartProcessError(QProcess::ProcessError error);
+        void onEngineDeath(int exitCode, QProcess::ExitStatus exitStatus);
 
         void tcpServerReady();
 };
--- a/QTfrontend/util/MessageDialog.cpp	Sun Jun 15 00:02:25 2014 +0200
+++ b/QTfrontend/util/MessageDialog.cpp	Sun Jun 15 04:33:54 2014 +0200
@@ -47,26 +47,26 @@
 
 int MessageDialog::ShowMessage(const QString & title, const QString & msg, QMessageBox::Icon icon, QWidget * parent)
 {
-    QMessageBox msgMsg(parent ? parent : HWApplication::activeWindow());
+    // if no parent try to use active window
+    parent = parent ? parent : HWApplication::activeWindow();
+
+    // didn't work? make child of hwform (e.g. for style and because modal)
+    if (!parent)
+    {
+        try
+        {
+            HWApplication * app = dynamic_cast<HWApplication*>(HWApplication::instance());
+            if (app->form)
+                parent = app->form;
+        }
+        catch (...) { /* nothing */ }
+    }
+
+    QMessageBox msgMsg(parent);
     msgMsg.setWindowTitle(title != NULL ? title : "Hedgewars");
     msgMsg.setText(msg);
     msgMsg.setIcon(icon);
     msgMsg.setWindowModality(Qt::WindowModal);
 
-    if (!parent)
-    {
-        try
-        {
-            /* workaround to make sure style is correct
-             * I'd rather assign the stylesheet to qApp directly (in main.cpp),
-             * but the current Stylesheet will ruin the look (e.g. map selection) :(
-             */
-            HWApplication * app = dynamic_cast<HWApplication*>(HWApplication::instance());
-            if (app->form)
-                msgMsg.setStyleSheet(app->form->styleSheet());
-        }
-        catch (...) { /* nothing */ }
-    }
-
     return msgMsg.exec();
 }
--- a/hedgewars/uConsts.pas	Sun Jun 15 00:02:25 2014 +0200
+++ b/hedgewars/uConsts.pas	Sun Jun 15 04:33:54 2014 +0200
@@ -26,15 +26,16 @@
 {$INCLUDE "config.inc"}
 
 const
-    HaltNoError      = 0;
-    HaltUsageError   = 1;
-    HaltFatalError   = 2;
-    HaltStartupError = 3;
+    HaltNoError         =  0;
+    HaltUsageError      =  1;
+    HaltFatalError      =  2;
+    HaltStartupError    =  3;
+    HaltFatalErrorNoIPC =  4;
 
     // for automatic tests
-    HaltTestSuccess  =   0;
-    HaltTestFailed   =  10;
-    HaltTestLuaError =  11;
+    HaltTestSuccess     =  0;
+    HaltTestFailed      =  10;
+    HaltTestLuaError    =  11;
 
 
     sfMax = 1000;
--- a/hedgewars/uIO.pas	Sun Jun 15 00:02:25 2014 +0200
+++ b/hedgewars/uIO.pas	Sun Jun 15 04:33:54 2014 +0200
@@ -416,7 +416,11 @@
     SendIPC('E' + s);
     // TODO: should we try to clean more stuff here?
     SDL_Quit;
-    halt(HaltFatalError);
+
+    if IPCSock <> nil then
+        halt(HaltFatalError)
+    else
+        halt(HaltFatalErrorNoIPC);
 end;
 
 procedure doPut(putX, putY: LongInt; fromAI: boolean);