Merge from default flibqtfrontend
authorunc0rr
Fri, 04 Jan 2013 21:44:40 +0400
branchflibqtfrontend
changeset 8363 0b4ac686fc44
parent 8306 50fe80adbfcb (diff)
parent 8362 89a6b7cc6f95 (current diff)
Merge from default
CMakeLists.txt
QTfrontend/CMakeLists.txt
QTfrontend/game.cpp
QTfrontend/game.h
QTfrontend/hwconsts.cpp.in
QTfrontend/hwconsts.h
QTfrontend/hwform.cpp
QTfrontend/main.cpp
QTfrontend/net/hwmap.cpp
QTfrontend/net/recorder.cpp
QTfrontend/net/tcpBase.cpp
QTfrontend/net/tcpBase.h
QTfrontend/team.cpp
QTfrontend/team.h
QTfrontend/ui/page/pageeditteam.cpp
QTfrontend/ui/page/pagemain.cpp
QTfrontend/ui/page/pagenettype.cpp
QTfrontend/ui/page/pagenettype.h
hedgewars/ArgParsers.inc
hedgewars/hwengine.pas
misc/physfs/CMakeLists.txt
project_files/hedgewars.pro
--- a/CMakeLists.txt	Fri Jan 04 19:42:49 2013 +0400
+++ b/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -277,6 +277,9 @@
 #main engine
 add_subdirectory(hedgewars)
 
+#frontend library
+add_subdirectory(project_files/frontlib)
+
 #Android related build scripts
 if(ANDROID)
     #run cmake -DANDROID=1 to enable this
--- a/QTfrontend/CMakeLists.txt	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -36,6 +36,7 @@
 include_directories(${FFMPEG_INCLUDE_DIR})
 include_directories(${CMAKE_SOURCE_DIR}/misc/physfs/src)
 include_directories(${CMAKE_SOURCE_DIR}/misc/physfs/extras)
+include_directories(${CMAKE_SOURCE_DIR}/project_files/frontlib)
 if(UNIX)
     # HACK: in freebsd cannot find iconv.h included via SDL.h
     include_directories("/usr/local/include")
@@ -115,6 +116,7 @@
     team.h
     util/DataManager.h
     util/LibavInteraction.h
+    util/frontlibpoller.h
     )
 
 set(hwfr_hdrs
@@ -178,10 +180,12 @@
 endif()
 
 list(APPEND HW_LINK_LIBS
+    frontlib
     physfs
     ${QT_LIBRARIES}
     ${SDL_LIBRARY}
     ${SDLMIXER_LIBRARY}
+    ${SDLNET_LIBRARY}
     ${FFMPEG_LIBRARIES}
     )
 
--- a/QTfrontend/game.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/game.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -34,16 +34,17 @@
 #include "proto.h"
 #include "binds.h"
 #include "campaign.h"
-
-#include <QTextStream>
 #include "ThemeModel.h"
+#include "frontlibpoller.h"
 
 QString training, campaign, campaignScript, campaignTeam; // TODO: Cleaner solution?
 
 HWGame::HWGame(GameUIConfig * config, GameCFGWidget * gamecfg, QString ammo, TeamSelWidget* pTeamSelWidget) :
-    TCPBase(true, 0),
-    ammostr(ammo),
-    m_pTeamSelWidget(pTeamSelWidget)
+    TCPBase(0)
+    , ammostr(ammo)
+    , m_pTeamSelWidget(pTeamSelWidget)
+    , m_conn(0)
+    , m_poller(0)
 {
     this->config = config;
     this->gamecfg = gamecfg;
@@ -53,28 +54,9 @@
 HWGame::~HWGame()
 {
     SetGameState(gsDestroyed);
-}
 
-void HWGame::onClientDisconnect()
-{
-    switch (gameType)
-    {
-        case gtDemo:
-            // for video recording we need demo anyway 
-            emit HaveRecord(rtNeither, demo);
-            break;
-        case gtNet:
-            emit HaveRecord(rtDemo, demo);
-            break;
-        default:
-            if (gameState == gsInterrupted || gameState == gsHalted)
-                emit HaveRecord(rtSave, demo);
-            else if (gameState == gsFinished)
-                emit HaveRecord(rtDemo, demo);
-            else
-                emit HaveRecord(rtNeither, demo);
-    }
-    SetGameState(gsStopped);
+    if(m_conn)
+        flib_gameconn_destroy(m_conn);
 }
 
 void HWGame::addKeyBindings(QByteArray * buf)
@@ -119,13 +101,13 @@
             HWProto::addStringToBuffer(buf, QString("eammdelay %1").arg(ammostr.mid(2 * cAmmoNumber, cAmmoNumber)));
             HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber)));
             if(gamecfg->schemeData(15).toBool() || !gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore"));
-            HWProto::addStringListToBuffer(buf,
-                                           team.teamGameConfig(gamecfg->getInitHealth(), config));
-            ;
+//            HWProto::addStringListToBuffer(buf,
+//                                           team.teamGameConfig(gamecfg->getInitHealth(), config));
+           ;
         }
     }
-    
-    RawSendIPC(buf);
+
+    //RawSendIPC(buf);
 }
 
 void HWGame::SendConfig()
@@ -133,48 +115,6 @@
     commonConfig();
 }
 
-void HWGame::SendQuickConfig()
-{
-    QByteArray teamscfg;
-    ThemeModel * themeModel = DataManager::instance().themeModel();
-
-    addKeyBindings(&teamscfg);
-
-    HWProto::addStringToBuffer(teamscfg, "TL");
-    HWProto::addStringToBuffer(teamscfg, QString("etheme %1")
-                               .arg((themeModel->rowCount() > 0) ? themeModel->index(rand() % themeModel->rowCount()).data().toString() : "steel"));
-    HWProto::addStringToBuffer(teamscfg, "eseed " + QUuid::createUuid().toString());
-
-    HWProto::addStringToBuffer(teamscfg, "e$template_filter 2");
-
-    HWTeam team1;
-    team1.setDifficulty(0);
-    team1.setColor(0);
-    team1.setNumHedgehogs(4);
-    HWNamegen::teamRandomNames(team1,true);
-    HWProto::addStringListToBuffer(teamscfg,
-                                   team1.teamGameConfig(100, config));
-
-    HWTeam team2;
-    team2.setDifficulty(4);
-    team2.setColor(1);
-    team2.setNumHedgehogs(4);
-    do
-        HWNamegen::teamRandomNames(team2,true);
-    while(!team2.name().compare(team1.name()) || !team2.hedgehog(0).Hat.compare(team1.hedgehog(0).Hat));
-    HWProto::addStringListToBuffer(teamscfg,
-                                   team2.teamGameConfig(100, config));
-
-    HWProto::addStringToBuffer(teamscfg, QString("eammloadt %1").arg(cDefaultAmmoStore->mid(0, cAmmoNumber)));
-    HWProto::addStringToBuffer(teamscfg, QString("eammprob %1").arg(cDefaultAmmoStore->mid(cAmmoNumber, cAmmoNumber)));
-    HWProto::addStringToBuffer(teamscfg, QString("eammdelay %1").arg(cDefaultAmmoStore->mid(2 * cAmmoNumber, cAmmoNumber)));
-    HWProto::addStringToBuffer(teamscfg, QString("eammreinf %1").arg(cDefaultAmmoStore->mid(3 * cAmmoNumber, cAmmoNumber)));
-    HWProto::addStringToBuffer(teamscfg, QString("eammstore"));
-    HWProto::addStringToBuffer(teamscfg, QString("eammstore"));
-    
-    RawSendIPC(teamscfg);
-}
-
 void HWGame::SendTrainingConfig()
 {
     QByteArray traincfg;
@@ -184,7 +124,7 @@
 
     addKeyBindings(&traincfg);
 
-    RawSendIPC(traincfg);
+    //RawSendIPC(traincfg);
 }
 
 void HWGame::SendCampaignConfig()
@@ -197,21 +137,21 @@
 
     addKeyBindings(&campaigncfg);
 
-    RawSendIPC(campaigncfg);
+    //RawSendIPC(campaigncfg);
 }
 
 void HWGame::SendNetConfig()
 {
     commonConfig();
 }
-
+/*
 void HWGame::ParseMessage(const QByteArray & msg)
 {
     switch(msg.at(1))
     {
         case '?':
         {
-            SendIPC("!");
+            //SendIPC("!");
             break;
         }
         case 'C':
@@ -282,7 +222,7 @@
             emit SendChat(msgbody);
             QByteArray buf;
             HWProto::addStringToBuffer(buf, "s" + HWProto::formatChatMsg(config->netNick(), msgbody) + "\x20\x20");
-            demo.append(buf);
+            //demo.append(buf);
             break;
         }
         case 'b':
@@ -316,25 +256,25 @@
             {
                 emit SendNet(msg);
             }
-            demo.append(msg);
+            //demo.append(msg);
         }
     }
-}
+}*/
 
 void HWGame::FromNet(const QByteArray & msg)
 {
-    RawSendIPC(msg);
+    //RawSendIPC(msg);
 }
 
 void HWGame::FromNetChat(const QString & msg)
 {
     QByteArray buf;
     HWProto::addStringToBuffer(buf, 's' + msg + "\x20\x20");
-    RawSendIPC(buf);
+    //RawSendIPC(buf);
 }
 
 void HWGame::onClientRead()
-{
+{/*
     quint8 msglen;
     quint32 bufsize;
     while (!readbuffer.isEmpty() && ((bufsize = readbuffer.size()) > 0) &&
@@ -343,7 +283,7 @@
         QByteArray msg = readbuffer.left(msglen + 1);
         readbuffer.remove(0, msglen + 1);
         ParseMessage(msg);
-    }
+    }*/
 }
 
 QStringList HWGame::getArguments()
@@ -354,7 +294,7 @@
 
     arguments << "--internal"; //Must be passed as first argument
     arguments << "--port";
-    arguments << QString("%1").arg(ipc_port);
+    arguments << QString::number(flib_gameconn_getport(m_conn));
     arguments << "--prefix";
     arguments << datadir->absolutePath();
     arguments << "--user-prefix";
@@ -406,35 +346,83 @@
     }
 
     // read demo
-    toSendBuf = demofile.readAll();
+    //toSendBuf = demofile.readAll();
 
     // run engine
-    demo.clear();
-    Start(false);
+    //demo.clear();
+    start(false);
     SetGameState(gsStarted);
 }
 
 void HWGame::StartNet()
 {
     gameType = gtNet;
-    demo.clear();
-    Start(false);
+    //demo.clear();
+    start(false);
     SetGameState(gsStarted);
 }
 
 void HWGame::StartLocal()
 {
     gameType = gtLocal;
-    demo.clear();
-    Start(false);
+    //demo.clear();
+    start(false);
     SetGameState(gsStarted);
 }
 
 void HWGame::StartQuick()
 {
+    ThemeModel * themeModel = DataManager::instance().themeModel();
     gameType = gtQLocal;
-    demo.clear();
-    Start(false);
+
+    flib_gamesetup gameSetup;
+    gameSetup.style = NULL;
+    gameSetup.gamescheme = flib_scheme_create("Default");
+    gameSetup.map = flib_map_create_regular(
+                QUuid::createUuid().toString().toAscii().constData()
+                , themeModel->rowCount() > 0 ? themeModel->index(rand() % themeModel->rowCount()).data().toString().toUtf8().constData() : "Sheep"
+                , 2);
+    gameSetup.teamlist = flib_teamlist_create();
+
+    // add teams
+    HWTeam team1;
+    team1.setDifficulty(0);
+    team1.setColor(0);
+    team1.setNumHedgehogs(4);
+    HWNamegen::teamRandomNames(team1, true);
+
+    HWTeam team2;
+    team2.setDifficulty(4);
+    team2.setColor(1);
+    team2.setNumHedgehogs(4);
+    do
+        HWNamegen::teamRandomNames(team2,true);
+    while(!team2.name().compare(team1.name()) || !team2.hedgehogHat(0).compare(team1.hedgehogHat(0)));
+
+    QList<flib_team *> teams;
+    teams << team1.toFlibTeam() << team2.toFlibTeam();
+
+    for(int i = 0; i < 2; ++i)
+    {
+        flib_team *team = teams[i];
+        team->hogsInGame = 4;
+        team->remoteDriven = false;
+        for(int h = 0; h < HEDGEHOGS_PER_TEAM; ++h)
+        {
+            team->hogs[h].weaponset = flib_weaponset_create("Default");
+            team->hogs[h].initialHealth = 100;
+        }
+        flib_teamlist_insert(gameSetup.teamlist, team, 0);
+    }
+
+
+    m_conn = flib_gameconn_create(config->netNick().toUtf8().constData(), &gameSetup, false);
+
+    flib_teamlist_destroy(gameSetup.teamlist);
+    flib_map_destroy(gameSetup.map);
+    flib_scheme_destroy(gameSetup.gamescheme);
+
+    start(false);
     SetGameState(gsStarted);
 }
 
@@ -442,8 +430,8 @@
 {
     gameType = gtTraining;
     training = "Missions/Training/" + file + ".lua";
-    demo.clear();
-    Start(false);
+    //demo.clear();
+    start(false);
     SetGameState(gsStarted);
 }
 
@@ -453,8 +441,8 @@
     campaign = camp;
     campaignScript = "Missions/Campaign/" + camp + "/" + campScript;
     campaignTeam = campTeam;
-    demo.clear();
-    Start(false);
+    //demo.clear();
+    start(false);
     SetGameState(gsStarted);
 }
 
@@ -464,7 +452,7 @@
     emit GameStateChanged(state);
     if (gameType == gtCampaign)
     {
-      emit CampStateChanged(1);
+      emit campStateChanged(1);
     }
 }
 
@@ -472,18 +460,18 @@
 {
     QByteArray buf;
     HWProto::addStringToBuffer(buf, QString("efinish"));
-    RawSendIPC(buf);
+    //RawSendIPC(buf);
 }
 
 void HWGame::sendCampaignVar(const QByteArray &varToSend)
 {
     QString varToFind(varToSend);
-    QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + campaignTeam + ".hwt", QSettings::IniFormat, 0);
+    QSettings teamfile("/Teams/" + campaignTeam + ".hwt", QSettings::IniFormat, 0);
     teamfile.setIniCodec("UTF-8");
     QString varValue = teamfile.value("Campaign " + campaign + "/" + varToFind, "").toString();
     QByteArray command;
     HWProto::addStringToBuffer(command, "V." + varValue);
-    RawSendIPC(command);
+    //RawSendIPC(command);
 }
 
 void HWGame::writeCampaignVar(const QByteArray & varVal)
@@ -495,8 +483,80 @@
     QString varToWrite = QString::fromUtf8(varVal.left(i));
     QString varValue = QString::fromUtf8(varVal.mid(i + 1));
 
-    QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + campaignTeam + ".hwt", QSettings::IniFormat, 0);
+    QSettings teamfile("/Teams/" + campaignTeam + ".hwt", QSettings::IniFormat, 0);
     teamfile.setIniCodec("UTF-8");
     teamfile.setValue("Campaign " + campaign + "/" + varToWrite, varValue);
 }
 
+
+void HWGame::onChat(void* context, const char *msg, bool teamchat)
+{
+    HWGame * game = (HWGame *) context;
+
+    if(teamchat)
+        emit game->SendTeamMessage(QString::fromUtf8(msg));
+    else
+        emit game->SendChat(QString::fromUtf8(msg));
+}
+
+void HWGame::onConnect(void* context)
+{
+    HWGame * game = (HWGame *) context;
+}
+
+void HWGame::onDisconnect(void* context, int reason)
+{
+    HWGame * game = (HWGame *) context;
+    /*
+        switch (gameType)
+        {
+            case gtDemo:
+                // for video recording we need demo anyway
+                emit HaveRecord(rtNeither, demo);
+                break;
+            case gtNet:
+                emit HaveRecord(rtDemo, demo);
+                break;
+            default:
+                if (gameState == gsInterrupted || gameState == gsHalted)
+                    emit HaveRecord(rtSave, demo);
+                else if (gameState == gsFinished)
+                    emit HaveRecord(rtDemo, demo);
+                else
+                    emit HaveRecord(rtNeither, demo);
+        }*/
+
+     game->SetGameState(gsStopped);
+     game->clientDisconnected();
+
+     delete game->m_poller;
+}
+
+void HWGame::onEngineMessage(void *context, const uint8_t *em, size_t size)
+{
+    HWGame * game = (HWGame *) context;
+}
+
+void HWGame::onErrorMessage(void* context, const char *msg)
+{
+    HWGame * game = (HWGame *) context;
+
+    emit game->ErrorMessage(QString("Last two engine messages:\n%1").arg(QString::fromUtf8(msg)));
+}
+
+void HWGame::onGameRecorded(void *context, const uint8_t *record, size_t size, bool isSavegame)
+{
+    HWGame * game = (HWGame *) context;
+}
+
+void HWGame::onEngineStart()
+{
+    flib_gameconn_onChat(m_conn, onChat, this);
+    flib_gameconn_onConnect(m_conn, onConnect, this);
+    flib_gameconn_onDisconnect(m_conn, onDisconnect, this);
+    flib_gameconn_onEngineMessage(m_conn, onEngineMessage, this);
+    flib_gameconn_onErrorMessage(m_conn, onErrorMessage, this);
+    flib_gameconn_onGameRecorded(m_conn, onGameRecorded, this);
+
+    m_poller = new FrontLibPoller((void (*)(void *))flib_gameconn_tick, m_conn, this);
+}
--- a/QTfrontend/game.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/game.h	Fri Jan 04 21:44:40 2013 +0400
@@ -24,6 +24,7 @@
 #include "namegen.h"
 
 #include "tcpBase.h"
+#include "frontlib.h"
 
 class GameUIConfig;
 class GameCFGWidget;
@@ -47,7 +48,7 @@
     rtNeither,
 };
 
-bool checkForDir(const QString & dir);
+class FrontLibPoller;
 
 class HWGame : public TCPBase
 {
@@ -69,7 +70,7 @@
     protected:
         virtual QStringList getArguments();
         virtual void onClientRead();
-        virtual void onClientDisconnect();
+        void onEngineStart();
 
     signals:
         void SendNet(const QByteArray & msg);
@@ -79,7 +80,7 @@
         void GameStats(char type, const QString & info);
         void HaveRecord(RecordType type, const QByteArray & record);
         void ErrorMessage(const QString &);
-        void CampStateChanged(int);
+        void campStateChanged(int);
 
     public slots:
         void FromNet(const QByteArray & msg);
@@ -96,24 +97,32 @@
             gtCampaign = 6,
             gtSave     = 7,
         };
-        char msgbuf[MAXMSGCHARS];
+        //char msgbuf[MAXMSGCHARS];
         QString ammostr;
         GameUIConfig * config;
         GameCFGWidget * gamecfg;
         TeamSelWidget* m_pTeamSelWidget;
         GameType gameType;
 
+        flib_gameconn * m_conn;
+        FrontLibPoller * m_poller;
+
         void addKeyBindings(QByteArray * buf);
         void commonConfig();
         void SendConfig();
-        void SendQuickConfig();
         void SendNetConfig();
         void SendTrainingConfig();
         void SendCampaignConfig();
-        void ParseMessage(const QByteArray & msg);
         void SetGameState(GameState state);
         void sendCampaignVar(const QByteArray & varToSend);
         void writeCampaignVar(const QByteArray &varVal);
+
+        static void onChat(void* context, const char *msg, bool teamchat);
+        static void onConnect(void* context);
+        static void onDisconnect(void* context, int reason);
+        static void onEngineMessage(void *context, const uint8_t *em, size_t size);
+        static void onErrorMessage(void* context, const char *msg);
+        static void onGameRecorded(void *context, const uint8_t *record, size_t size, bool isSavegame);
 };
 
 #endif
--- a/QTfrontend/hwconsts.cpp.in	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/hwconsts.cpp.in	Fri Jan 04 21:44:40 2013 +0400
@@ -19,6 +19,7 @@
 #include <QStandardItemModel>
 
 #include "hwconsts.h"
+#include "frontlib.h"
 
 QString * cProtoVer = new QString("${HEDGEWARS_PROTO_VER}");
 QString * cDataDir = new QString("${HEDGEWARS_DATADIR}");
@@ -61,7 +62,11 @@
             AMMOLINE_PORTALS_DELAY AMMOLINE_PORTALS_CRATE ))
         ;
 
-unsigned int colors[] = HW_TEAMCOLOR_ARRAY;
+#ifndef UINT32_C
+#define UINT32_C
+#endif
+
+quint32 colors[] = HW_TEAMCOLOR_ARRAY;
 
 QString * netHost = new QString();
 quint16 netPort = NETGAME_DEFAULT_PORT;
--- a/QTfrontend/hwconsts.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/hwconsts.h	Fri Jan 04 21:44:40 2013 +0400
@@ -43,7 +43,7 @@
 extern int cAmmoNumber;
 extern QList< QPair<QString, QString> > cDefaultAmmos;
 
-extern unsigned int colors[];
+extern quint32 colors[];
 
 extern QString * netHost;
 extern quint16 netPort;
@@ -62,10 +62,10 @@
 
 #define HEDGEHOGS_PER_TEAM           8
 
-#define AMMOLINE_DEFAULT_QT     "9391929422199121032235111001201000000211110101011111101"
-#define AMMOLINE_DEFAULT_PROB   "0405040541600655546554464776576666666155510101115411101"
-#define AMMOLINE_DEFAULT_DELAY  "0000000000000205500000040007004000000000220000000600000"
-#define AMMOLINE_DEFAULT_CRATE  "1311110312111111123114111111111111111211111101111111101"
+//#define AMMOLINE_DEFAULT_QT     "9391929422199121032235111001201000000211110101011111101"
+//#define AMMOLINE_DEFAULT_PROB   "0405040541600655546554464776576666666155510101115411101"
+//#define AMMOLINE_DEFAULT_DELAY  "0000000000000205500000040007004000000000220000000600000"
+//#define AMMOLINE_DEFAULT_CRATE  "1311110312111111123114111111111111111211111101111111101"
 
 #define AMMOLINE_CRAZY_QT       "9999999999999999992999999999999999299999999909999992909"
 #define AMMOLINE_CRAZY_PROB     "1111110111111111111111111111111111111111111101111111101"
@@ -104,40 +104,3 @@
 #define SEASON_EASTER 8
 
 #define NETGAME_DEFAULT_PORT 46631
-
-
-// see http://en.wikipedia.org/wiki/List_of_colors
-/*define HW_TEAMCOLOR_ARRAY  {0xff007fff, /. azure          ./ \
-                              0xffdd0000, /. classic red    ./ \
-                              0xff3e9321, /. classic green  ./ \
-                              0xffa23dbb, /. classic purple ./ \
-                              0xffffb347, /. pastel orange  ./ \
-                              0xffcfcfc4, /. pastel gray    ./ \
-                              0xffbff000, /. lime           ./ \
-                              0xffffef00, /. yellow         ./ \
-                              // add new colors here
-                              0 }*/
-/*
-#define HW_TEAMCOLOR_ARRAY  { 0xffd12b42, /. red    ./ \
-                              0xff4980c1, /. blue   ./ \
-                              0xff6ab530, /. green  ./ \
-                              0xffbc64c4, /. purple ./ \
-                              0xffe76d14, /. orange ./ \
-                              0xff3fb6e6, /. cyan   ./ \
-                              0xffe3e90c, /. yellow ./ \
-                              0xff61d4ac, /. mint   ./ \
-                              0xfff1c3e1, /. pink   ./ \
-                              // add new colors here
-                              0 }*/
-/* another set. this one is a merge of mikade/bugq colours w/ a bit of channel feedback */
-#define HW_TEAMCOLOR_ARRAY  { 0xffff0204, /* red    */ \
-                              0xff4980c1, /* blue   */ \
-                              0xff1de6ba, /* teal   */ \
-                              0xffb541ef, /* purple */ \
-                              0xffe55bb0, /* pink   */ \
-                              0xff20bf00, /* green  */ \
-                              0xfffe8b0e, /* orange */ \
-                              0xff5f3605, /* brown  */ \
-                              0xffffff01, /* yellow */ \
-                              /* add new colors here */ \
-                              0 }
--- a/QTfrontend/hwform.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/hwform.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -126,6 +126,8 @@
 
 GameUIConfig* HWForm::config = NULL;
 
+bool checkForDir(const QString & dir);
+
 HWForm::HWForm(QWidget *parent, QString styleSheet)
     : QMainWindow(parent)
     , game(0)
@@ -1593,7 +1595,7 @@
 void HWForm::CreateGame(GameCFGWidget * gamecfg, TeamSelWidget* pTeamSelWidget, QString ammo)
 {
     game = new HWGame(config, gamecfg, ammo, pTeamSelWidget);
-    connect(game, SIGNAL(CampStateChanged(int)), this, SLOT(UpdateCampaignPageProgress(int)));
+    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);
--- a/QTfrontend/main.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/main.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -37,6 +37,8 @@
 #include "DataManager.h"
 #include "FileEngine.h"
 
+#include "frontlib.h"
+
 #ifdef _WIN32
 #include <Shlobj.h>
 #elif defined __APPLE__
@@ -165,6 +167,8 @@
 
     FileEngineHandler engine(argv[0]);
 
+    flib_init();
+
     app.setAttribute(Qt::AA_DontShowIconsInMenus,false);
 
     QStringList arguments = app.arguments();
@@ -345,7 +349,13 @@
 
     app.form = new HWForm(NULL, style);
     app.form->show();
+
     if(splash)
         splash->close();
-    return app.exec();
+
+    int r = app.exec();
+
+    flib_quit();
+
+    return r;
 }
--- a/QTfrontend/net/hwmap.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/hwmap.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -19,14 +19,21 @@
 
 #include "hwconsts.h"
 #include "hwmap.h"
+#include "frontlibpoller.h"
 
 HWMap::HWMap(QObject * parent) :
-    TCPBase(false, parent)
+    TCPBase(parent)
 {
+    m_conn = NULL;
+    m_map = NULL;
 }
 
 HWMap::~HWMap()
 {
+    if(m_conn)
+        flib_mapconn_destroy(m_conn);
+    if(m_map)
+        flib_map_destroy(m_map);
 }
 
 bool HWMap::couldBeRemoved()
@@ -34,18 +41,43 @@
     return !m_hasStarted;
 }
 
-void HWMap::getImage(const QString & seed, int filter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData)
+void HWMap::getImage(const QString & seed, int filter, int mapgen, int maze_size, const QByteArray & drawMapData)
 {
-    m_seed = seed;
-    templateFilter = filter;
-    m_mapgen = mapgen;
-    m_maze_size = maze_size;
-    if(mapgen == MAPGEN_DRAWN) m_drawMapData = drawMapData;
-    Start(true);
+    switch(mapgen)
+    {
+        case MAPGEN_REGULAR: m_map =
+                flib_map_create_regular(
+                    seed.toUtf8().constData()
+                    , ""
+                    , filter);
+                break;
+        case MAPGEN_MAZE: m_map =
+                flib_map_create_maze(
+                    seed.toUtf8().constData()
+                    , ""
+                    , maze_size);
+                break;
+        case MAPGEN_DRAWN: m_map =
+                flib_map_create_drawn(
+                    seed.toUtf8().constData()
+                    , ""
+                    , (const uint8_t*)drawMapData.constData()
+                    , drawMapData.size()
+                    );
+                break;
+        default:
+            Q_ASSERT_X(false, "HWMap::getImage", "Unknown generator");
+    }
+    qDebug(m_map->seed);
+    start(true);
 }
 
 QStringList HWMap::getArguments()
 {
+    Q_ASSERT(m_conn);
+
+    int ipc_port = flib_mapconn_getport(m_conn);
+
     QStringList arguments;
     arguments << "--internal";
     arguments << "--port";
@@ -56,45 +88,32 @@
     return arguments;
 }
 
-void HWMap::onClientDisconnect()
+void HWMap::onSuccess(void *context, const uint8_t *bitmap, int numHedgehogs)
 {
-    if (readbuffer.size() == 128 * 32 + 1)
-    {
-        quint8 *buf = (quint8*) readbuffer.constData();
-        QImage im(buf, 256, 128, QImage::Format_Mono);
-        im.setNumColors(2);
-        emit HHLimitReceived(buf[128 * 32]);
-        emit ImageReceived(im);
-    }
+    HWMap * hwMap = (HWMap *)context;
+
+    QImage im(bitmap, MAPIMAGE_WIDTH, MAPIMAGE_HEIGHT, QImage::Format_Mono);
+    im.setNumColors(2);
+    emit hwMap->HHLimitReceived(numHedgehogs);
+    emit hwMap->ImageReceived(im);
+
+    hwMap->clientDisconnected();
 }
 
-void HWMap::SendToClientFirst()
+void HWMap::onFailure(void *context, const char *errormessage)
 {
-    SendIPC(QString("eseed %1").arg(m_seed).toUtf8());
-    SendIPC(QString("e$template_filter %1").arg(templateFilter).toUtf8());
-    SendIPC(QString("e$mapgen %1").arg(m_mapgen).toUtf8());
+    HWMap * hwMap = (HWMap *)context;
 
-    switch (m_mapgen)
-    {
-        case MAPGEN_MAZE:
-            SendIPC(QString("e$maze_size %1").arg(m_maze_size).toUtf8());
-            break;
+    qWarning(errormessage);
+
+    hwMap->clientDisconnected();
+}
 
-        case MAPGEN_DRAWN:
-        {
-            QByteArray data = m_drawMapData;
-            while(data.size() > 0)
-            {
-                QByteArray tmp = data;
-                tmp.truncate(200);
-                SendIPC("edraw " + tmp);
-                data.remove(0, 200);
-            }
-            break;
-        }
-        default:
-            ;
-    }
+void HWMap::onEngineStart()
+{
+    m_conn = flib_mapconn_create(m_map);
+    flib_mapconn_onSuccess(m_conn, onSuccess, this);
+    flib_mapconn_onFailure(m_conn, onFailure, this);
 
-    SendIPC("!");
+    new FrontLibPoller((void (*)(void *))flib_mapconn_tick, m_conn, this);
 }
--- a/QTfrontend/net/hwmap.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/hwmap.h	Fri Jan 04 21:44:40 2013 +0400
@@ -23,16 +23,10 @@
 #include <QByteArray>
 #include <QString>
 #include <QImage>
+#include <QTimer>
 
 #include "tcpBase.h"
-
-enum MapGenerator
-{
-    MAPGEN_REGULAR,
-    MAPGEN_MAZE,
-    MAPGEN_DRAWN,
-    MAPGEN_MAP
-};
+#include "frontlib.h"
 
 class HWMap : public TCPBase
 {
@@ -41,13 +35,12 @@
     public:
         HWMap(QObject *parent = 0);
         virtual ~HWMap();
-        void getImage(const QString & seed, int templateFilter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData);
+        void getImage(const QString & seed, int templateFilter, int mapgen, int maze_size, const QByteArray & drawMapData);
         bool couldBeRemoved();
 
     protected:
-        virtual QStringList getArguments();
-        virtual void onClientDisconnect();
-        virtual void SendToClientFirst();
+        QStringList getArguments();
+        void onEngineStart();
 
     signals:
         void ImageReceived(const QImage newImage);
@@ -55,11 +48,12 @@
 
     private:
         QString m_seed;
-        int templateFilter;
-        MapGenerator m_mapgen;
-        int m_maze_size;
-        QByteArray m_drawMapData;
 
+        flib_mapconn * m_conn;
+        flib_map * m_map;
+
+        static void onSuccess(void *context, const uint8_t *bitmap, int numHedgehogs);
+        static void onFailure(void *context, const char *errormessage);
     private slots:
 };
 
--- a/QTfrontend/net/newnetclient.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/newnetclient.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -132,9 +132,9 @@
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; ++i)
     {
         cmd.append(delimeter);
-        cmd.append(team.hedgehog(i).Name);
+        cmd.append(team.hedgehogName(i));
         cmd.append(delimeter);
-        cmd.append(team.hedgehog(i).Hat);
+        cmd.append(team.hedgehogHat(i));
     }
     RawSendNet(cmd);
 }
--- a/QTfrontend/net/recorder.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/recorder.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -47,16 +47,21 @@
     if (queue.empty())
         numRecorders--;
     else
-        queue.takeFirst()->Start(false);
+        queue.takeFirst()->start(false);
 }
 
 void HWRecorder::onClientDisconnect()
 {
 }
 
+void HWRecorder::onEngineStart()
+{
+
+}
+
 void HWRecorder::onClientRead()
 {
-    quint8 msglen;
+/*    quint8 msglen;
     quint32 bufsize;
     while (!readbuffer.isEmpty() && ((bufsize = readbuffer.size()) > 0) &&
             ((msglen = readbuffer.data()[0]) < bufsize))
@@ -75,12 +80,12 @@
             finished = true;
             break;
         }
-    }
+    }*/
 }
 
 void HWRecorder::EncodeVideo(const QByteArray & record)
 {
-    toSendBuf = record;
+    /*toSendBuf = record;
     toSendBuf.replace(QByteArray("\x02TD"), QByteArray("\x02TV"));
     toSendBuf.replace(QByteArray("\x02TL"), QByteArray("\x02TV"));
     toSendBuf.replace(QByteArray("\x02TN"), QByteArray("\x02TV"));
@@ -92,7 +97,7 @@
         Start(false); // run engine
     }
     else
-        queue.push_back(this);
+        queue.push_back(this);*/
 }
 
 QStringList HWRecorder::getArguments()
@@ -103,7 +108,7 @@
 
     arguments << "--internal";
     arguments << "--port";
-    arguments << QString("%1").arg(ipc_port);
+    //arguments << QString("%1").arg(ipc_port);
     arguments << "--prefix";
     arguments << datadir->absolutePath();
     arguments << "--user-prefix";
--- a/QTfrontend/net/recorder.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/recorder.h	Fri Jan 04 21:44:40 2013 +0400
@@ -45,6 +45,7 @@
         virtual QStringList getArguments();
         virtual void onClientRead();
         virtual void onClientDisconnect();
+        void onEngineStart();
 
     signals:
         void onProgress(float progress); // 0 < progress < 1
--- a/QTfrontend/net/tcpBase.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/tcpBase.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -65,63 +65,23 @@
 #endif
 
 QList<TCPBase*> srvsList;
-QPointer<QTcpServer> TCPBase::IPCServer(0);
 
 TCPBase::~TCPBase()
 {
     // make sure this object is not in the server list anymore
     srvsList.removeOne(this);
-
-    if (IPCSocket)
-        IPCSocket->deleteLater();
-
 }
 
-TCPBase::TCPBase(bool demoMode, QObject *parent) :
+TCPBase::TCPBase(QObject *parent) :
     QObject(parent),
-    m_hasStarted(false),
-    m_isDemoMode(demoMode),
-    IPCSocket(0)
+    m_hasStarted(false)
 {
-    if(!IPCServer)
-    {
-        IPCServer = new QTcpServer(0);
-        IPCServer->setMaxPendingConnections(1);
-        if (!IPCServer->listen(QHostAddress::LocalHost))
-        {
-            QMessageBox deniedMsg(QApplication::activeWindow());
-            deniedMsg.setIcon(QMessageBox::Critical);
-            deniedMsg.setWindowTitle(QMessageBox::tr("TCP - Error"));
-            deniedMsg.setText(QMessageBox::tr("Unable to start the server: %1.").arg(IPCServer->errorString()));
-            deniedMsg.setWindowModality(Qt::WindowModal);
-            deniedMsg.exec();
 
-            exit(0); // FIXME - should be graceful exit here (lower Critical -> Warning above when implemented)
-        }
-    }
-
-    ipc_port=IPCServer->serverPort();
-}
-
-void TCPBase::NewConnection()
-{
-    if(IPCSocket)
-    {
-        // connection should be already finished
-        return;
-    }
-    disconnect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
-    IPCSocket = IPCServer->nextPendingConnection();
-    if(!IPCSocket) return;
-    connect(IPCSocket, SIGNAL(disconnected()), this, SLOT(ClientDisconnect()));
-    connect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
-    SendToClientFirst();
 }
 
 void TCPBase::RealStart()
 {
-    connect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection()));
-    IPCSocket = 0;
+    onEngineStart();
 
 #ifdef HWLIBRARY
     QThread *thread = new QThread;
@@ -137,9 +97,9 @@
     thread->start();
 #else
     QProcess * process;
+
     process = new QProcess();
-    connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError)));
-    QStringList arguments=getArguments();
+    QStringList arguments = getArguments();
 
     // redirect everything written on stdout/stderr
     if(isDevBuild)
@@ -150,50 +110,26 @@
     m_hasStarted = true;
 }
 
-void TCPBase::ClientDisconnect()
+void TCPBase::clientDisconnected()
 {
-    disconnect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
-    onClientDisconnect();
-
-    emit isReadyNow();
-    IPCSocket->deleteLater();
+    emit nextPlease();
 
     deleteLater();
 }
 
-void TCPBase::ClientRead()
-{
-    QByteArray readed=IPCSocket->readAll();
-    if(readed.isEmpty()) return;
-    readbuffer.append(readed);
-    onClientRead();
-}
-
-void TCPBase::StartProcessError(QProcess::ProcessError error)
+void TCPBase::iStart()
 {
-    QMessageBox deniedMsg(QApplication::activeWindow());
-    deniedMsg.setIcon(QMessageBox::Critical);
-    deniedMsg.setWindowTitle(QMessageBox::tr("TCP - Error"));
-    deniedMsg.setText(QMessageBox::tr("Unable to run engine at ") + bindir->absolutePath() + "/hwengine\n" +
-                      QMessageBox::tr("Error code: %1").arg(error));
-    deniedMsg.setWindowModality(Qt::WindowModal);
-    deniedMsg.exec();
-
-    ClientDisconnect();
-}
-
-void TCPBase::tcpServerReady()
-{
-    disconnect(srvsList.first(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
+    disconnect(srvsList.first(), SIGNAL(nextPlease()), this, SLOT(iStart()));
 
     RealStart();
 }
 
-void TCPBase::Start(bool couldCancelPreviousRequest)
+void TCPBase::start(bool couldCancelPreviousRequest)
 {
     if(srvsList.isEmpty())
     {
         srvsList.push_back(this);
+
         RealStart();
     }
     else
@@ -205,56 +141,15 @@
         {
             srvsList.removeLast();
             last->deleteLater();
-            Start(couldCancelPreviousRequest);
+            start(couldCancelPreviousRequest);
         } else
         {
-            connect(srvsList.last(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
+            connect(srvsList.last(), SIGNAL(nextPlease()), this, SLOT(iStart()));
             srvsList.push_back(this);
         }
     }
 }
 
-void TCPBase::onClientRead()
-{
-}
-
-void TCPBase::onClientDisconnect()
-{
-}
-
-void TCPBase::SendToClientFirst()
-{
-}
-
-void TCPBase::SendIPC(const QByteArray & buf)
-{
-    if (buf.size() > MAXMSGCHARS) return;
-    quint8 len = buf.size();
-    RawSendIPC(QByteArray::fromRawData((char *)&len, 1) + buf);
-}
-
-void TCPBase::RawSendIPC(const QByteArray & buf)
-{
-    if (!IPCSocket)
-    {
-        toSendBuf += buf;
-    }
-    else
-    {
-        if (toSendBuf.size() > 0)
-        {
-            IPCSocket->write(toSendBuf);
-            if(m_isDemoMode) demo.append(toSendBuf);
-            toSendBuf.clear();
-        }
-        if(!buf.isEmpty())
-        {
-            IPCSocket->write(buf);
-            if(m_isDemoMode) demo.append(buf);
-        }
-    }
-}
-
 bool TCPBase::couldBeRemoved()
 {
     return false;
--- a/QTfrontend/net/tcpBase.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/net/tcpBase.h	Fri Jan 04 21:44:40 2013 +0400
@@ -21,64 +21,37 @@
 #define _TCPBASE_INCLUDED
 
 #include <QObject>
-#include <QTcpServer>
-#include <QTcpSocket>
-#include <QByteArray>
-#include <QString>
-#include <QDir>
 #include <QProcess>
-#include <QPointer>
-
-#include <QImage>
-
-#define MAXMSGCHARS 255
 
 class TCPBase : public QObject
 {
         Q_OBJECT
 
     public:
-        TCPBase(bool demoMode, QObject * parent = 0);
+        TCPBase(QObject * parent = 0);
         virtual ~TCPBase();
 
         virtual bool couldBeRemoved();
 
     signals:
-        void isReadyNow();
+        void nextPlease();
 
     protected:
         bool m_hasStarted;
-        quint16 ipc_port;
+        int m_port;
 
-        void Start(bool couldCancelPreviousRequest);
-
-        QByteArray readbuffer;
+        void start(bool couldCancelPreviousRequest);
 
-        QByteArray toSendBuf;
-        QByteArray demo;
+        virtual QStringList getArguments() = 0;
+        virtual void onEngineStart() = 0;
 
-        void SendIPC(const QByteArray & buf);
-        void RawSendIPC(const QByteArray & buf);
-
-        virtual QStringList getArguments()=0;
-        virtual void onClientRead();
-        virtual void onClientDisconnect();
-        virtual void SendToClientFirst();
+        void clientDisconnected();
 
     private:
-        static QPointer<QTcpServer> IPCServer;
-
-        bool m_isDemoMode;
         void RealStart();
-        QPointer<QTcpSocket> IPCSocket;
 
     private slots:
-        void NewConnection();
-        void ClientDisconnect();
-        void ClientRead();
-        void StartProcessError(QProcess::ProcessError error);
-
-        void tcpServerReady();
+        void iStart();
 };
 
 #ifdef HWLIBRARY
--- a/QTfrontend/team.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/team.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -28,289 +28,183 @@
 #include "team.h"
 #include "hwform.h"
 #include "DataManager.h"
-#include "gameuiconfig.h"
+
+HWTeam::HWTeam(const QString & teamname, QObject *parent) :
+    QObject(parent)
+{
+    QList<QByteArray> baList;
 
-HWTeam::HWTeam(const QString & teamname) :
-    QObject(0)
-    , m_difficulty(0)
-    , m_numHedgehogs(4)
-    , m_isNetTeam(false)
-{
-    m_name = teamname;
-    OldTeamName = m_name;
+    flib_team team;
+    memset(&team, 0, sizeof(team));
+    baList << teamname.toUtf8();
+    team.name = baList.last().data();
+    team.grave = const_cast<char *>("Statue");
+    team.fort = const_cast<char *>("Plane");
+    team.voicepack = const_cast<char *>("Default");
+    team.flag = const_cast<char *>("hedgewars");
+
     for (int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
-        m_hedgehogs.append(HWHog());
-        m_hedgehogs[i].Name = (QLineEdit::tr("hedgehog %1").arg(i+1));
-        m_hedgehogs[i].Hat = "NoHat";
+        baList << QLineEdit::tr("hedgehog %1").arg(i+1).toUtf8();
+        team.hogs[i].name = baList.last().data();
+        team.hogs[i].hat = const_cast<char *>("NoHat");
     }
-    m_grave = "Statue";
-    m_fort = "Plane";
-    m_voicepack = "Default";
-    m_flag = "hedgewars";
+
+    m_oldTeamName = teamname;
+
+    QVector<flib_binding> binds(BINDS_NUMBER);
     for(int i = 0; i < BINDS_NUMBER; i++)
     {
-        m_binds.append(BindAction());
-        m_binds[i].action = cbinds[i].action;
-        m_binds[i].strbind = QString();
+        baList << cbinds[i].action.toUtf8();
+        binds[i].action = baList.last().data();
+        baList << cbinds[i].strbind.toUtf8();
+        binds[i].binding = baList.last().data();
     }
-    m_rounds = 0;
-    m_wins = 0;
-    m_campaignProgress = 0;
-    m_color = 0;
+    team.bindings = binds.data();
+    team.bindingCount = binds.size();
+
+    m_team = flib_team_copy(&team);
 }
 
-HWTeam::HWTeam(const QStringList& strLst) :
-    QObject(0)
-    , m_numHedgehogs(4)
-    , m_isNetTeam(true)
+HWTeam::HWTeam(const QStringList& strLst, QObject *parent) :
+    QObject(parent)
 {
+    QList<QByteArray> baList;
+
     // net teams are configured from QStringList
     if(strLst.size() != 23) throw HWTeamConstructException();
-    m_name = strLst[0];
-    m_grave = strLst[1];
-    m_fort = strLst[2];
-    m_voicepack = strLst[3];
-    m_flag = strLst[4];
-    m_owner = strLst[5];
-    m_difficulty = strLst[6].toUInt();
-    for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
-    {
-        m_hedgehogs.append(HWHog());
-        m_hedgehogs[i].Name=strLst[i * 2 + 7];
-        m_hedgehogs[i].Hat=strLst[i * 2 + 8];
-// Somehow claymore managed an empty hat.  Until we figure out how, this should avoid a repeat
-// Checking net teams is probably pointless, but can't hurt.
-        if (m_hedgehogs[i].Hat.isEmpty()) m_hedgehogs[i].Hat = "NoHat";
-    }
-    m_rounds = 0;
-    m_wins = 0;
-    m_campaignProgress = 0;
-    m_color = 0;
-}
+    flib_team team;
+    memset(&team, 0, sizeof(team));
 
-HWTeam::HWTeam() :
-    QObject(0)
-    , m_difficulty(0)
-    , m_numHedgehogs(4)
-    , m_isNetTeam(false)
-{
-    m_name = QString("Team");
+    for(int i = 0; i < 6; ++i)
+        baList << strLst[i].toUtf8();
+    team.name = baList[0].data();
+    m_oldTeamName = strLst[0];
+    team.grave = baList[1].data();
+    team.fort = baList[2].data();
+    team.voicepack = baList[3].data();
+    team.flag = baList[4].data();
+    team.ownerName = baList[5].data();
+    int difficulty = strLst[6].toUInt();
+
     for (int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
-        m_hedgehogs.append(HWHog());
-        m_hedgehogs[i].Name.sprintf("hedgehog %d", i);
-        m_hedgehogs[i].Hat = "NoHat";
+        baList << strLst[i * 2 + 7].toUtf8();
+        team.hogs[i].name = baList.last().data();
+
+        QString hat = strLst[i * 2 + 8];
+        if (hat.isEmpty())
+            team.hogs[i].hat = const_cast<char *>("NoHat");
+        else
+        {
+            baList << hat.toUtf8();
+            team.hogs[i].hat = baList.last().data();
+        }
+
+        team.hogs[i].difficulty = difficulty;
     }
 
-    m_grave = QString("Simple"); // default
-    m_fort = QString("Island"); // default
-    m_voicepack = "Default";
-    m_flag = "hedgewars";
+    m_oldTeamName = strLst[0];
 
+    QVector<flib_binding> binds(BINDS_NUMBER);
     for(int i = 0; i < BINDS_NUMBER; i++)
     {
-        m_binds.append(BindAction());
-        m_binds[i].action = cbinds[i].action;
-        m_binds[i].strbind = QString();
+        baList << cbinds[i].action.toUtf8();
+        binds[i].action = baList.last().data();
+        baList << cbinds[i].strbind.toUtf8();
+        binds[i].binding = baList.last().data();
     }
-    m_rounds = 0;
-    m_wins = 0;
-    m_campaignProgress = 0;
-    m_color = 0;
+    team.bindings = binds.data();
+    team.bindingCount = binds.size();
+
+    m_team = flib_team_copy(&team);
 }
 
+
 HWTeam::HWTeam(const HWTeam & other) :
-    QObject(0)
-    , OldTeamName(other.OldTeamName)
-    , m_name(other.m_name)
-    , m_grave(other.m_grave)
-    , m_fort(other.m_fort)
-    , m_flag(other.m_flag)
-    , m_voicepack(other.m_voicepack)
-    , m_hedgehogs(other.m_hedgehogs)
-    , m_difficulty(other.m_difficulty)
-    , m_binds(other.m_binds)
-    , m_numHedgehogs(other.m_numHedgehogs)
-    , m_color(other.m_color)
-    , m_isNetTeam(other.m_isNetTeam)
-    , m_owner(other.m_owner)
-    , m_campaignProgress(other.m_campaignProgress)
-    , m_rounds(other.m_rounds)
-    , m_wins(other.m_wins)
-//      , AchievementProgress(other.AchievementProgress)
+    QObject(other.parent())
+    , m_oldTeamName(other.m_oldTeamName)
+    , m_team(flib_team_copy(other.m_team))
 {
-
+    m_team->hogsInGame = other.m_team->hogsInGame;
+    m_team->remoteDriven = other.m_team->remoteDriven;
 }
 
 HWTeam & HWTeam::operator = (const HWTeam & other)
 {
     if(this != &other)
     {
-        OldTeamName = other.OldTeamName;
-        m_name = other.m_name;
-        m_grave = other.m_grave;
-        m_fort = other.m_fort;
-        m_flag = other.m_flag;
-        m_voicepack = other.m_voicepack;
-        m_hedgehogs = other.m_hedgehogs;
-        m_difficulty = other.m_difficulty;
-        m_binds = other.m_binds;
-        m_numHedgehogs = other.m_numHedgehogs;
-        m_color = other.m_color;
-        m_isNetTeam = other.m_isNetTeam;
-        m_owner = other.m_owner;
-        m_campaignProgress = other.m_campaignProgress;
-        m_rounds = other.m_rounds;
-        m_wins = other.m_wins;
-        m_color = other.m_color;
+        m_oldTeamName = other.m_oldTeamName;
+        m_team = flib_team_copy(other.m_team);
+
+        m_team->hogsInGame = other.m_team->hogsInGame;
+        m_team->remoteDriven = other.m_team->remoteDriven;
     }
 
     return *this;
 }
 
+HWTeam::~HWTeam()
+{
+    if(m_team)
+        flib_team_destroy(m_team);
+}
+
 bool HWTeam::loadFromFile()
 {
-    QSettings teamfile(QString("physfs://Teams/%1.hwt").arg(m_name), QSettings::IniFormat, 0);
-    teamfile.setIniCodec("UTF-8");
-    m_name = teamfile.value("Team/Name", m_name).toString();
-    m_grave = teamfile.value("Team/Grave", "Statue").toString();
-    m_fort = teamfile.value("Team/Fort", "Plane").toString();
-    m_voicepack = teamfile.value("Team/Voicepack", "Default").toString();
-    m_flag = teamfile.value("Team/Flag", "hedgewars").toString();
-    m_difficulty = teamfile.value("Team/Difficulty", 0).toInt();
-    m_rounds = teamfile.value("Team/Rounds", 0).toInt();
-    m_wins = teamfile.value("Team/Wins", 0).toInt();
-    m_campaignProgress = teamfile.value("Team/CampaignProgress", 0).toInt();
-    for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
-    {
-        QString hh = QString("Hedgehog%1/").arg(i);
-        m_hedgehogs[i].Name = teamfile.value(hh + "Name", QString("hedgehog %1").arg(i+1)).toString();
-        m_hedgehogs[i].Hat = teamfile.value(hh + "Hat", "NoHat").toString();
-        m_hedgehogs[i].Rounds = teamfile.value(hh + "Rounds", 0).toInt();
-        m_hedgehogs[i].Kills = teamfile.value(hh + "Kills", 0).toInt();
-        m_hedgehogs[i].Deaths = teamfile.value(hh + "Deaths", 0).toInt();
-        m_hedgehogs[i].Suicides = teamfile.value(hh + "Suicides", 0).toInt();
-    }
-    for(int i = 0; i < BINDS_NUMBER; i++)
-        m_binds[i].strbind = teamfile.value(QString("Binds/%1").arg(m_binds[i].action), QString()).toString();
-    for(int i = 0; i < MAX_ACHIEVEMENTS; i++)
-        if(achievements[i][0][0])
-            AchievementProgress[i] = teamfile.value(QString("Achievements/%1").arg(achievements[i][0]), 0).toUInt();
-        else
-            break;
-    return true;
+    QString name = QString::fromUtf8(m_team->name);
+
+    if(m_team)
+        flib_team_destroy(m_team);
+
+    m_team = flib_team_from_ini(QString("/Teams/%1.hwt").arg(name).toUtf8().data());
+
+    return m_team != NULL;
 }
 
 bool HWTeam::fileExists()
 {
-    QFile f(QString("physfs://Teams/%1.hwt").arg(m_name));
+    QFile f(QString("physfs://Teams/%1.hwt").arg(name()));
     return f.exists();
 }
 
 bool HWTeam::deleteFile()
 {
-    if(m_isNetTeam)
+    if(m_team->remoteDriven)
         return false;
-    QFile cfgfile(QString("physfs://Teams/%1.hwt").arg(m_name));
+
+    QFile cfgfile(QString("physfs://Teams/%1.hwt").arg(name()));
     cfgfile.remove();
     return true;
 }
 
 bool HWTeam::saveToFile()
 {
-    if (OldTeamName != m_name)
+    if (m_oldTeamName != name())
     {
-        QFile cfgfile(QString("physfs://Teams/%1.hwt").arg(OldTeamName));
+        QFile cfgfile(QString("physfs://Teams/%1.hwt").arg(m_oldTeamName));
         cfgfile.remove();
-        OldTeamName = m_name;
+        m_oldTeamName = name();
     }
 
-    QSettings teamfile(QString("physfs://Teams/%1.hwt").arg(m_name), QSettings::IniFormat, 0);
-    teamfile.setIniCodec("UTF-8");
-    teamfile.setValue("Team/Name", m_name);
-    teamfile.setValue("Team/Grave", m_grave);
-    teamfile.setValue("Team/Fort", m_fort);
-    teamfile.setValue("Team/Voicepack", m_voicepack);
-    teamfile.setValue("Team/Flag", m_flag);
-    teamfile.setValue("Team/Difficulty", m_difficulty);
-    teamfile.setValue("Team/Rounds", m_rounds);
-    teamfile.setValue("Team/Wins", m_wins);
-    teamfile.setValue("Team/CampaignProgress", m_campaignProgress);
-
-    for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
-    {
-        QString hh = QString("Hedgehog%1/").arg(i);
-        teamfile.setValue(hh + "Name", m_hedgehogs[i].Name);
-        teamfile.setValue(hh + "Hat", m_hedgehogs[i].Hat);
-        teamfile.setValue(hh + "Rounds", m_hedgehogs[i].Rounds);
-        teamfile.setValue(hh + "Kills", m_hedgehogs[i].Kills);
-        teamfile.setValue(hh + "Deaths", m_hedgehogs[i].Deaths);
-        teamfile.setValue(hh + "Suicides", m_hedgehogs[i].Suicides);
-    }
-    for(int i = 0; i < BINDS_NUMBER; i++)
-        teamfile.setValue(QString("Binds/%1").arg(m_binds[i].action), m_binds[i].strbind);
-    for(int i = 0; i < MAX_ACHIEVEMENTS; i++)
-        if(achievements[i][0][0])
-            teamfile.setValue(QString("Achievements/%1").arg(achievements[i][0]), AchievementProgress[i]);
-        else
-            break;
-
-    return true;
+    return flib_team_to_ini(QString("physfs://Teams/%1.hwt").arg(name()).toUtf8(), m_team) == 0;
 }
 
-QStringList HWTeam::teamGameConfig(quint32 InitHealth, GameUIConfig * config) const
-{
-    QStringList sl;
-    if (m_isNetTeam)
-    {
-        sl.push_back(QString("eaddteam %3 %1 %2").arg(qcolor().rgb() & 0xffffff).arg(m_name).arg(QString(QCryptographicHash::hash(m_owner.toUtf8(), QCryptographicHash::Md5).toHex())));
-        sl.push_back("erdriven");
-    }
-    else sl.push_back(QString("eaddteam %3 %1 %2").arg(qcolor().rgb() & 0xffffff).arg(m_name).arg(playerHash));
-
-    sl.push_back(QString("egrave " + m_grave));
-    sl.push_back(QString("efort " + m_fort));
-    sl.push_back(QString("evoicepack " + m_voicepack));
-    sl.push_back(QString("eflag " + m_flag));
-
-    if (!m_isNetTeam)
-    {
-        for(int i = 0; i < BINDS_NUMBER; i++)
-        {
-            if(m_binds[i].strbind.isEmpty() || m_binds[i].strbind == "default")
-                sl.push_back(QString("ebind " + config->bind(i) + " " + m_binds[i].action));
-            else
-                sl.push_back(QString("ebind " + m_binds[i].strbind + " " + m_binds[i].action));
-        }
-    }
-
-    for (int t = 0; t < m_numHedgehogs; t++)
-    {
-        sl.push_back(QString("eaddhh %1 %2 %3")
-                     .arg(QString::number(m_difficulty),
-                          QString::number(InitHealth),
-                          m_hedgehogs[t].Name));
-        sl.push_back(QString("ehat %1")
-                     .arg(m_hedgehogs[t].Hat));
-    }
-    return sl;
-}
 
 bool HWTeam::isNetTeam() const
 {
-    return m_isNetTeam;
+    return m_team->remoteDriven;
 }
 
 
 bool HWTeam::operator==(const HWTeam& t1) const
 {
-    return m_name==t1.m_name;
+    return qstrcmp(m_team->name, t1.m_team->name) == 0;
 }
 
 bool HWTeam::operator<(const HWTeam& t1) const
 {
-    return m_name<t1.m_name; // if names are equal - test if it is net team
+    return qstrcmp(m_team->name, t1.m_team->name) < 0; // if names are equal - test if it is net team
 }
 
 
@@ -320,27 +214,45 @@
 // name
 QString HWTeam::name() const
 {
-    return m_name;
+    return QString::fromUtf8(m_team->name);
 }
+
 void HWTeam::setName(const QString & name)
 {
-    m_name = name;
+    free(m_team->name);
+
+    m_team->name = strdup(name.toUtf8().constData());
+}
+
+QString HWTeam::hedgehogName(int index) const
+{
+    return QString::fromUtf8(m_team->hogs[index].name);
 }
 
-// single hedgehog
-const HWHog & HWTeam::hedgehog(unsigned int idx) const
+QString HWTeam::hedgehogHat(int index) const
 {
-    return m_hedgehogs[idx];
+    return QString::fromUtf8(m_team->hogs[index].hat);
 }
-void HWTeam::setHedgehog(unsigned int idx, HWHog hh)
+
+void HWTeam::setHedgehogName(int index, const QString & name)
 {
-    m_hedgehogs[idx] = hh;
+    free(m_team->hogs[index].name);
+
+    m_team->hogs[index].name = strdup(name.toUtf8().constData());
 }
 
+void HWTeam::setHedgehogHat(int index, const QString & hat)
+{
+    free(m_team->hogs[index].hat);
+
+    m_team->hogs[index].hat = strdup(hat.toUtf8().constData());
+}
+
+
 // owner
 QString HWTeam::owner() const
 {
-    return m_owner;
+    return QString::fromUtf8(m_team->ownerName);
 }
 
 
@@ -348,105 +260,126 @@
 // difficulty
 unsigned int HWTeam::difficulty() const
 {
-    return m_difficulty;
+    return m_team->hogs[0].difficulty;
 }
+
 void HWTeam::setDifficulty(unsigned int level)
 {
-    m_difficulty = level;
+    for(int i = 0; i < HEDGEHOGS_PER_TEAM; ++i)
+        m_team->hogs[i].difficulty = level;
 }
 
 // color
 int HWTeam::color() const
 {
-    return m_color;
+    return m_team->colorIndex;
 }
 
 QColor HWTeam::qcolor() const
 {
-    return DataManager::instance().colorsModel()->item(m_color)->data().value<QColor>();
+    return DataManager::instance().colorsModel()->item(m_team->colorIndex)->data().value<QColor>();
 }
 
 void HWTeam::setColor(int color)
 {
-    m_color = color % DataManager::instance().colorsModel()->rowCount();
+    m_team->colorIndex = color % DataManager::instance().colorsModel()->rowCount();
 }
 
 
 // binds
 QString HWTeam::keyBind(unsigned int idx) const
 {
-    return m_binds[idx].strbind;
+    return QString::fromUtf8(m_team->bindings[idx].binding);
 }
+
 void HWTeam::bindKey(unsigned int idx, const QString & key)
 {
-    m_binds[idx].strbind = key;
+    free(m_team->bindings[idx].binding);
+
+    m_team->bindings[idx].binding = strdup(key.toUtf8().constData());
 }
 
 // flag
-void    HWTeam::setFlag(const QString & flag)
+void HWTeam::setFlag(const QString & flag)
 {
-    m_flag = flag;
+    free(m_team->flag);
+
+    m_team->flag = strdup(flag.toUtf8().constData());
 }
+
 QString HWTeam::flag() const
 {
-    return m_flag;
+    return QString::fromUtf8(m_team->flag);
 }
 
 // fort
-void    HWTeam::setFort(const QString & fort)
+void HWTeam::setFort(const QString & fort)
 {
-    m_fort = fort;
+    free(m_team->fort);
+
+    m_team->fort = strdup(fort.toUtf8().constData());
 }
+
 QString HWTeam::fort() const
 {
-    return m_fort;
+    return QString::fromUtf8(m_team->fort);
 }
 
 // grave
 void HWTeam::setGrave(const QString & grave)
 {
-    m_grave = grave;
+    free(m_team->grave);
+
+    m_team->grave = strdup(grave.toUtf8().constData());
 }
+
 QString HWTeam::grave() const
 {
-    return m_grave;
+    return QString::fromUtf8(m_team->grave);
 }
 
 // voicepack - getter/setter
 void HWTeam::setVoicepack(const QString & voicepack)
 {
-    m_voicepack = voicepack;
+    free(m_team->voicepack);
+
+    m_team->voicepack = strdup(voicepack.toUtf8().constData());
 }
+
 QString HWTeam::voicepack() const
 {
-    return m_voicepack;
+    return QString::fromUtf8(m_team->voicepack);
 }
 
 
 // campaignProgress - getter
 unsigned int HWTeam::campaignProgress() const
 {
-    return m_campaignProgress;
-};
+    return m_team->campaignProgress;
+}
 
 // amount of hedgehogs
 unsigned char HWTeam::numHedgehogs() const
 {
-    return m_numHedgehogs;
+    return m_team->hogsInGame;
 }
+
 void HWTeam::setNumHedgehogs(unsigned char num)
 {
-    m_numHedgehogs = num;
+    m_team->hogsInGame = num;
 }
 
-
-
 // rounds+wins - incrementors
 void HWTeam::incRounds()
 {
-    m_rounds++;
+    m_team->rounds++;
 }
 void HWTeam::incWins()
 {
-    m_wins++;
+    m_team->wins++;
 }
+
+flib_team * HWTeam::toFlibTeam()
+{
+    return flib_team_copy(m_team);
+}
--- a/QTfrontend/team.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/team.h	Fri Jan 04 21:44:40 2013 +0400
@@ -25,6 +25,7 @@
 #include "binds.h"
 #include "achievements.h"
 #include "hwconsts.h"
+#include "frontlib.h"
 
 class HWForm;
 class GameUIConfig;
@@ -33,14 +34,6 @@
 {
 };
 
-// structure for customization and statistics of a single hedgehog
-struct HWHog
-{
-    QString Name;
-    QString Hat;
-    int Rounds, Kills, Deaths, Suicides;
-};
-
 // class representing a team
 class HWTeam : public QObject
 {
@@ -49,10 +42,10 @@
     public:
 
         // constructors
-        HWTeam(const QString & teamname);
-        HWTeam(const QStringList& strLst);
-        HWTeam();
+        HWTeam(const QString & teamname = QString("Team"), QObject * parent = 0);
+        HWTeam(const QStringList& strLst, QObject * parent = 0);
         HWTeam(const HWTeam & other);
+        ~HWTeam();
 
         // file operations
         static HWTeam loadFromFile(const QString & teamName);
@@ -69,7 +62,7 @@
         QString flag() const;
         QString fort() const;
         QString grave() const;
-        const HWHog & hedgehog(unsigned int idx) const;
+        //const HWHog & hedgehog(unsigned int idx) const;
         bool isNetTeam() const;
         QString keyBind(unsigned int idx) const;
         QString name() const;
@@ -83,17 +76,20 @@
         void setFlag(const QString & flag);
         void setFort(const QString & fort);
         void setGrave(const QString & grave);
-        void setHedgehog(unsigned int idx, HWHog hh);
         void setName(const QString & name);
         void setNumHedgehogs(unsigned char num);
         void setVoicepack(const QString & voicepack);
 
+        QString hedgehogName(int index) const;
+        QString hedgehogHat(int index) const;
+        void setHedgehogName(int index, const QString & name);
+        void setHedgehogHat(int index, const QString & hat);
+
         // increments for statistical info
         void incRounds();
         void incWins();
 
-        // convert team info into strings for further computation
-        QStringList teamGameConfig(quint32 InitHealth, GameUIConfig * config) const;
+        flib_team * toFlibTeam();
 
         // comparison operators
         bool operator == (const HWTeam& t1) const;
@@ -104,30 +100,10 @@
         void setColor(int color);
 
     private:
-
-        QString OldTeamName;
+        QString m_oldTeamName;
 
         // class members that contain the general team info and settings
-        QString m_name;
-        QString m_grave;
-        QString m_fort;
-        QString m_flag;
-        QString m_voicepack;
-        QList<HWHog> m_hedgehogs;
-        quint8 m_difficulty;
-        QList<BindAction> m_binds;
-
-        // class members that contain info for the current game setup
-        quint8 m_numHedgehogs;
-        int m_color;
-        bool m_isNetTeam;
-        QString m_owner;
-
-        // class members that contain statistics, etc.
-        unsigned int m_campaignProgress;
-        unsigned int m_rounds;
-        unsigned int m_wins;
-        unsigned int AchievementProgress[MAX_ACHIEVEMENTS];
+        flib_team * m_team;
 };
 
 #endif
--- a/QTfrontend/ui/page/pageeditteam.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -370,14 +370,13 @@
 
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
-        HWHog hh = team.hedgehog(i);
-
-        HHNameEdit[i]->setText(hh.Name);
+        HHNameEdit[i]->setText(team.hedgehogName(i));
 
-        if (hh.Hat.startsWith("Reserved"))
-            hh.Hat = "Reserved "+hh.Hat.remove(0,40);
+        QString hat = team.hedgehogHat(i);
+        if (hat.startsWith("Reserved"))
+            hat = "Reserved " + hat.mid(40);
 
-        HHHats[i]->setCurrentIndex(HHHats[i]->findData(hh.Hat, Qt::DisplayRole));
+        HHHats[i]->setCurrentIndex(HHHats[i]->findData(hat, Qt::DisplayRole));
     }
 
     CBGrave->setCurrentIndex(CBGrave->findText(team.grave()));
@@ -407,14 +406,13 @@
 
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
-        HWHog hh;
-        hh.Name = HHNameEdit[i]->text();
-        hh.Hat = HHHats[i]->currentText();
+        QString hat = HHHats[i]->currentText();
 
-        if (hh.Hat.startsWith("Reserved"))
-            hh.Hat = "Reserved"+m_playerHash+hh.Hat.remove(0,9);
+        if (hat.startsWith("Reserved"))
+            hat = "Reserved" + m_playerHash + hat.mid(9);
 
-        team.setHedgehog(i,hh);
+        team.setHedgehogName(i, HHNameEdit[i]->text());
+        team.setHedgehogHat(i, hat);
     }
 
     team.setGrave(CBGrave->currentText());
--- a/QTfrontend/ui/page/pagemain.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/page/pagemain.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -21,6 +21,7 @@
 #include <QPushButton>
 #include <QLabel>
 #include <QTime>
+#include <QTextStream>
 
 #include "pagemain.h"
 #include "hwconsts.h"
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -108,7 +108,7 @@
 
     connect(pMapContainer, SIGNAL(seedChanged(const QString &)), this, SLOT(seedChanged(const QString &)));
     connect(pMapContainer, SIGNAL(mapChanged(const QString &)), this, SLOT(mapChanged(const QString &)));
-    connect(pMapContainer, SIGNAL(mapgenChanged(MapGenerator)), this, SLOT(mapgenChanged(MapGenerator)));
+    connect(pMapContainer, SIGNAL(mapgenChanged(int)), this, SLOT(mapgenChanged(int)));
     connect(pMapContainer, SIGNAL(mazeSizeChanged(int)), this, SLOT(maze_sizeChanged(int)));
     connect(pMapContainer, SIGNAL(themeChanged(const QString &)), this, SLOT(themeChanged(const QString &)));
     connect(pMapContainer, SIGNAL(newTemplateFilter(int)), this, SLOT(templateFilterChanged(int)));
@@ -343,7 +343,7 @@
         }
         if (param == "MAPGEN")
         {
-            pMapContainer->setMapgen((MapGenerator)value.toUInt());
+            pMapContainer->setMapgen(value.toInt());
             return;
         }
         if (param == "MAZE_SIZE")
@@ -382,7 +382,7 @@
 
             pMapContainer->setAllMapParameters(
                 slValue[0],
-                (MapGenerator)slValue[1].toUInt(),
+                slValue[1].toInt(),
                 slValue[2].toUInt(),
                 seed,
                 slValue[4].toUInt()
@@ -553,7 +553,7 @@
     emit paramChanged("SCRIPT", QStringList(name));
 }
 
-void GameCFGWidget::mapgenChanged(MapGenerator m)
+void GameCFGWidget::mapgenChanged(int m)
 {
     emit paramChanged("MAPGEN", QStringList(QString::number(m)));
 }
--- a/QTfrontend/ui/widget/gamecfgwidget.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/widget/gamecfgwidget.h	Fri Jan 04 21:44:40 2013 +0400
@@ -69,7 +69,7 @@
         void scriptChanged(int);
         void jumpToSchemes();
         void jumpToWeapons();
-        void mapgenChanged(MapGenerator m);
+        void mapgenChanged(int m);
         void maze_sizeChanged(int s);
         void onDrawnMapChanged(const QByteArray & data);
         void updateModelViews();
--- a/QTfrontend/ui/widget/mapContainer.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -44,6 +44,7 @@
     mapgen(MAPGEN_REGULAR),
     m_previewSize(256, 128)
 {
+    m_mapInfo.type = MapModel::GeneratedMap;
     hhSmall.load(":/res/hh_small.png");
     hhLimit = 18;
     templateFilter = 0;
@@ -254,7 +255,7 @@
             cbMazeSize->hide();
             break;
         default:
-            mapgen = MAPGEN_MAP;
+            mapgen = MAPGEN_NAMED;
             gbThemes->hide();
             lblFilter->hide();
             cbTemplateFilter->hide();
@@ -339,7 +340,7 @@
 
 QString HWMapContainer::getCurrentMap() const
 {
-    if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
+    if(chooseMap->currentIndex() < MAPGEN_NAMED) return QString();
     return(m_curMap);
 }
 
@@ -468,7 +469,7 @@
         updatePreview();
 }
 
-MapGenerator HWMapContainer::get_mapgen(void) const
+int HWMapContainer::get_mapgen(void) const
 {
     return mapgen;
 }
@@ -491,7 +492,7 @@
         updatePreview();
 }
 
-void HWMapContainer::intSetMapgen(MapGenerator m)
+void HWMapContainer::intSetMapgen(int m)
 {
     if (mapgen != m)
     {
@@ -508,7 +509,7 @@
             case MAPGEN_DRAWN:
                 m_mapInfo.type = MapModel::HandDrawnMap;
                 break;
-            case MAPGEN_MAP:
+            case MAPGEN_NAMED:
                 switch (m_mapInfo.type)
                 {
                     case MapModel::GeneratedMap:
@@ -521,17 +522,17 @@
                 break;
         }
 
-        if(m != MAPGEN_MAP)
+        if(m != MAPGEN_NAMED)
             chooseMap->setCurrentIndex(m);
 
         emit mapgenChanged(m);
     }
 }
 
-void HWMapContainer::setMapgen(MapGenerator m)
+void HWMapContainer::setMapgen(int m)
 {
     intSetMapgen(m);
-    if(m != MAPGEN_MAP)
+    if(m != MAPGEN_NAMED)
         updatePreview();
 }
 
@@ -619,7 +620,7 @@
     }
 }
 
-void HWMapContainer::setAllMapParameters(const QString &map, MapGenerator m, int mazesize, const QString &seed, int tmpl)
+void HWMapContainer::setAllMapParameters(const QString &map, int m, int mazesize, const QString &seed, int tmpl)
 {
     intSetMapgen(m);
     intSetMazeSize(mazesize);
--- a/QTfrontend/ui/widget/mapContainer.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/widget/mapContainer.h	Fri Jan 04 21:44:40 2013 +0400
@@ -55,7 +55,7 @@
         QString getCurrentScheme() const;
         QString getCurrentWeapons() const;
         quint32 getTemplateFilter() const;
-        MapGenerator get_mapgen(void) const;
+        int get_mapgen(void) const;
         int getMazeSize(void) const;
         bool getCurrentIsMission() const;
         QByteArray getDrawnMapData();
@@ -69,10 +69,10 @@
         void setMap(const QString & map);
         void setTheme(const QString & theme);
         void setTemplateFilter(int);
-        void setMapgen(MapGenerator m);
+        void setMapgen(int m);
         void setMazeSize(int size);
         void setDrawnMapData(const QByteArray & ar);
-        void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl);
+        void setAllMapParameters(const QString & map, int m, int mazesize, const QString & seed, int tmpl);
         void updateModelViews();
         void onPreviewMapDestroyed(QObject * map);
 
@@ -81,7 +81,7 @@
         void mapChanged(const QString & map);
         void themeChanged(const QString & theme);
         void newTemplateFilter(int filter);
-        void mapgenChanged(MapGenerator m);
+        void mapgenChanged(int m);
         void mazeSizeChanged(int s);
         void drawMapRequested();
         void drawnMapChanged(const QByteArray & data);
@@ -119,12 +119,12 @@
         QComboBox* cbTemplateFilter;
         QLabel *maze_size_label;
         QComboBox *cbMazeSize;
-        MapGenerator mapgen;
+        int mapgen;
         DrawMapScene drawMapScene;
 
         void intSetSeed(const QString & seed);
         void intSetMap(const QString & map);
-        void intSetMapgen(MapGenerator m);
+        void intSetMapgen(int m);
         void intSetTemplateFilter(int);
         void intSetMazeSize(int size);
         void updatePreview();
--- a/QTfrontend/ui/widget/selectWeapon.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/ui/widget/selectWeapon.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -84,7 +84,7 @@
     QFrame(parent),
     m_numItems(numItems)
 {
-    wconf = new QSettings(cfgdir->absolutePath() + "/weapons.ini", QSettings::IniFormat, this);
+    wconf = new QSettings("physfs://weapons.ini", QSettings::IniFormat, this);
 
     for(int i = 0; i < cDefaultAmmos.size(); ++i)
         wconf->setValue(cDefaultAmmos[i].first, cDefaultAmmos[i].second);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/frontlibpoller.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,21 @@
+#include <QTimerEvent>
+
+#include "frontlibpoller.h"
+
+FrontLibPoller::FrontLibPoller(void (*poll)(void * data), void *data, QObject *parent) :
+    QObject(parent)
+{
+    m_poll = poll;
+    m_data = data;
+
+    if(m_data)
+        m_timer.start(50, this);
+}
+
+void FrontLibPoller::timerEvent(QTimerEvent *event)
+{
+    if(event->timerId() == m_timer.timerId())
+        m_poll(m_data);
+    else
+        QObject::timerEvent(event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/frontlibpoller.h	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,22 @@
+#ifndef FRONTLIBPOLLER_H
+#define FRONTLIBPOLLER_H
+
+#include <QObject>
+#include <QBasicTimer>
+
+class FrontLibPoller : public QObject
+{
+    Q_OBJECT
+public:
+    explicit FrontLibPoller(void (*poll)(void *), void * data, QObject *parent = 0);
+
+private:
+    QBasicTimer m_timer;
+
+    void (*m_poll)(void *);
+    void * m_data;
+
+    void timerEvent(QTimerEvent *event);
+};
+
+#endif // FRONTLIBPOLLER_H
--- a/QTfrontend/util/namegen.cpp	Fri Jan 04 19:42:49 2013 +0400
+++ b/QTfrontend/util/namegen.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -64,24 +64,20 @@
 
     if ((TypesHatnames[kind].size()) <= 0)
     {
-        dicts = dictsForHat(team.hedgehog(0).Hat);
+        dicts = dictsForHat(team.hedgehogHat(0));
         dict  = dictContents(dicts[rand()%(dicts.size())]);
     }
 
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
         if ((TypesHatnames[kind].size()) > 0)
-        {
-            HWHog hh = team.hedgehog(i);
-            hh.Hat = TypesHatnames[kind][rand()%(TypesHatnames[kind].size())];
-            team.setHedgehog(i,hh);
-        }
+            team.setHedgehogHat(i, TypesHatnames[kind][rand()%(TypesHatnames[kind].size())]);
 
         // there is a chance that this hog has the same hat as the previous one
         // let's reuse the hat-specific dict in this case
-        if ((i == 0) || (team.hedgehog(i).Hat != team.hedgehog(i-1).Hat))
+        if ((i == 0) || (team.hedgehogHat(i) != team.hedgehogHat(i-1)))
         {
-            dicts = dictsForHat(team.hedgehog(i).Hat);
+            dicts = dictsForHat(team.hedgehogHat(i));
             dict  = dictContents(dicts[rand()%(dicts.size())]);
         }
 
@@ -93,7 +89,7 @@
 
 void HWNamegen::teamRandomName(HWTeam & team, const int HedgehogNumber)
 {
-    QStringList dicts = dictsForHat(team.hedgehog(HedgehogNumber).Hat);
+    QStringList dicts = dictsForHat(team.hedgehogHat(HedgehogNumber));
 
     QStringList dict = dictContents(dicts[rand()%(dicts.size())]);
 
@@ -106,18 +102,14 @@
 
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
-        namesDict.removeOne(team.hedgehog(i).Name);
+        namesDict.removeOne(team.hedgehogName(i));
     }
 
     // if our dict doesn't have any new names we'll have to use duplicates
     if (namesDict.size() < 1)
         namesDict = dict;
 
-    HWHog hh = team.hedgehog(HedgehogNumber);
-
-    hh.Name = namesDict[rand()%(namesDict.size())];
-
-    team.setHedgehog(HedgehogNumber, hh);
+    team.setHedgehogName(HedgehogNumber, namesDict[rand()%(namesDict.size())]);
 }
 
 QStringList HWNamegen::dictContents(const QString filename)
--- a/misc/physfs/CMakeLists.txt	Fri Jan 04 19:42:49 2013 +0400
+++ b/misc/physfs/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -124,6 +124,7 @@
     extras/physfsrwops.c
     extras/physfslualoader.c
     extras/hwpacksmounter.c
+    extras/physfsfgets.c
 )
 
 # Almost everything is "compiled" here, but things that don't apply to the
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/physfs/extras/physfsfgets.c	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+
+#include "physfsfgets.h"
+
+char * PHYSFS_fgets(char * str, int size, PHYSFS_file * f)
+{
+    int i = 0;
+    char c;
+
+    if(size <= 0 || PHYSFS_eof(f))
+        return NULL;
+
+    do
+    {
+        if (PHYSFS_readBytes(f, &c, 1) < 1)
+            break;
+
+        str[i] = c;
+        ++i;
+    } while(c != '\n' && i < size - 1);
+
+    str[i] = '\0';
+    if (i == 0)
+        return NULL;
+    else
+        return str;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/physfs/extras/physfsfgets.h	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,17 @@
+#ifndef PHYSFS_FGETS_H
+#define PHYSFS_FGETS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "physfs.h"
+
+char * PHYSFS_fgets(char * str, int size, PHYSFS_file * f);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/project_files/frontlib/CMakeLists.txt	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -7,6 +7,7 @@
 file(GLOB frontlib_src
         *.c *.h
         base64/*.c base64/*.h
+        iniparser/*.c iniparser/*.h
         ipc/*.c ipc/*.h
         md5/*.c md5/*.h
         model/*.c model/*.h
@@ -17,5 +18,7 @@
 include_directories(${SDL_INCLUDE_DIR})
 include_directories(${SDLNET_INCLUDE_DIR})
 include_directories(${ZLIB_INCLUDE_DIR})
+include_directories(${CMAKE_SOURCE_DIR}/misc/physfs/src)
+include_directories(${CMAKE_SOURCE_DIR}/misc/physfs/extras)
 
 add_library(frontlib STATIC ${frontlib_src})
--- a/project_files/frontlib/frontlib.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/frontlib.h	Fri Jan 04 21:44:40 2013 +0400
@@ -26,6 +26,10 @@
 #ifndef FRONTLIB_H_
 #define FRONTLIB_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "ipc/gameconn.h"
 #include "ipc/mapconn.h"
 #include "net/netconn.h"
@@ -45,4 +49,8 @@
  */
 void flib_quit();
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* FRONTLIB_H_ */
--- a/project_files/frontlib/hwconsts.h	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/hwconsts.h	Fri Jan 04 21:44:40 2013 +0400
@@ -44,8 +44,7 @@
 //! Used for sending scripts to the engine
 #define MULTIPLAYER_SCRIPT_PATH "Scripts/Multiplayer/"
 
-#define WEAPONS_COUNT 56
-
+#define WEAPONS_COUNT 55
 // TODO allow frontend to override these?
 /*! A merge of mikade/bugq colours w/ a bit of channel feedback */
 #define HW_TEAMCOLOR_ARRAY  { UINT32_C(0xffff0204), /*! red    */ \
@@ -60,6 +59,11 @@
                               /*! add new colors here */ \
                               0 } /*! Keep this 0 at the end */
 
+#define AMMOLINE_DEFAULT_QT     "9391929422199121032235111001201000000211110101011111101"
+#define AMMOLINE_DEFAULT_PROB   "0405040541600655546554464776576666666155510101115411101"
+#define AMMOLINE_DEFAULT_DELAY  "0000000000000205500000040007004000000000220000000600000"
+#define AMMOLINE_DEFAULT_CRATE  "1311110312111111123114111111111111111211111101111111101"
+
 extern const size_t flib_teamcolor_count;
 extern const uint32_t flib_teamcolors[];
 
--- a/project_files/frontlib/iniparser/iniparser.c	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/iniparser/iniparser.c	Fri Jan 04 21:44:40 2013 +0400
@@ -9,6 +9,8 @@
 /*---------------------------- Includes ------------------------------------*/
 #include <ctype.h>
 #include "iniparser.h"
+#include "physfs.h"
+#include "physfsfgets.h"
 
 /*---------------------------- Defines -------------------------------------*/
 #define ASCIILINESZ         (1024)
@@ -628,7 +630,7 @@
 /*--------------------------------------------------------------------------*/
 dictionary * iniparser_load(const char * ininame)
 {
-    FILE * in ;
+    PHYSFS_File * in ;
 
     char line    [ASCIILINESZ+1] ;
     char section [ASCIILINESZ+1] ;
@@ -643,14 +645,14 @@
 
     dictionary * dict ;
 
-    if ((in=fopen(ininame, "r"))==NULL) {
+    if ((in = PHYSFS_openRead(ininame))==NULL) {
         fprintf(stderr, "iniparser: cannot open %s\n", ininame);
         return NULL ;
     }
 
     dict = dictionary_new(0) ;
     if (!dict) {
-        fclose(in);
+        PHYSFS_close(in);
         return NULL ;
     }
 
@@ -660,7 +662,7 @@
     memset(val,     0, ASCIILINESZ);
     last=0 ;
 
-    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
+    while (PHYSFS_fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
         lineno++ ;
         len = (int)strlen(line)-1;
         if (len==0)
@@ -672,7 +674,7 @@
                     ininame,
                     lineno);
             dictionary_del(dict);
-            fclose(in);
+            PHYSFS_close(in);
             return NULL ;
         }
         /* Get rid of \n and spaces at end of line */
@@ -725,7 +727,7 @@
         dictionary_del(dict);
         dict = NULL ;
     }
-    fclose(in);
+    PHYSFS_close(in);
     return dict ;
 }
 
--- a/project_files/frontlib/model/weapon.c	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/model/weapon.c	Fri Jan 04 21:44:40 2013 +0400
@@ -56,10 +56,10 @@
 		if(newSet) {
 			newSet->name = flib_strdupnull(name);
 			if(newSet->name) {
-				setField(newSet->loadout, "", 0, false);
-				setField(newSet->crateprob, "", 0, false);
-				setField(newSet->crateammo, "", 0, false);
-				setField(newSet->delay, "", 0, false);
+				setField(newSet->loadout, AMMOLINE_DEFAULT_QT, strlen(AMMOLINE_DEFAULT_QT), false);
+				setField(newSet->crateprob, AMMOLINE_DEFAULT_PROB, strlen(AMMOLINE_DEFAULT_PROB), true);
+				setField(newSet->crateammo, AMMOLINE_DEFAULT_CRATE, strlen(AMMOLINE_DEFAULT_CRATE), true);
+				setField(newSet->delay, AMMOLINE_DEFAULT_DELAY, strlen(AMMOLINE_DEFAULT_DELAY), true);
 				result = newSet;
 				newSet = NULL;
 			}
--- a/project_files/frontlib/socket.c	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/socket.c	Fri Jan 04 21:44:40 2013 +0400
@@ -61,7 +61,7 @@
 	return result;
 }
 
-TCPsocket listen(uint16_t port) {
+TCPsocket flib_listen(uint16_t port) {
 	IPaddress addr;
 	addr.host = INADDR_ANY;
 	SDLNet_Write16(port, &addr.port);
@@ -77,7 +77,7 @@
 	if(result) {
 		if(port > 0) {
 			result->port = port;
-			result->sock = listen(result->port);
+			result->sock = flib_listen(result->port);
 		} else {
 			/* SDL_net does not seem to have a way to listen on a random unused port
 			   and find out which port that is, so let's try to find one ourselves. */
@@ -85,7 +85,7 @@
 			for(int i=0; !result->sock && i<1000; i++) {
 				// IANA suggests using ports in the range 49152-65535 for things like this
 				result->port = 49152+(rand()%(65536-49152));
-				result->sock = listen(result->port);
+				result->sock = flib_listen(result->port);
 			}
 		}
 		if(!result->sock) {
--- a/project_files/frontlib/util/util.c	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/frontlib/util/util.c	Fri Jan 04 21:44:40 2013 +0400
@@ -37,12 +37,18 @@
 }
 
 char *flib_vasprintf(const char *fmt, va_list args) {
-	char *result = NULL;
+    char *result = NULL;
 	if(!log_badargs_if(fmt==NULL)) {
-		int requiredSize = vsnprintf(NULL, 0, fmt, args)+1;					// Figure out how much memory we need,
-		if(!log_e_if(requiredSize<0, "Error formatting string with template \"%s\"", fmt)) {
+        va_list args_copy;
+        va_copy(args_copy, args);
+
+        int requiredSize = vsnprintf(NULL, 0, fmt, args_copy)+1;					// Figure out how much memory we need,
+
+        va_end(args_copy);
+
+        if(!log_e_if(requiredSize<0, "Error formatting string with template \"%s\"", fmt)) {
 			char *tmpbuf = flib_malloc(requiredSize);						// allocate it
-			if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) {	// and then do the actual formatting.
+            if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) {	// and then do the actual formatting.
 				result = tmpbuf;
 				tmpbuf = NULL;
 			}
--- a/project_files/hedgewars.pro	Fri Jan 04 19:42:49 2013 +0400
+++ b/project_files/hedgewars.pro	Fri Jan 04 21:44:40 2013 +0400
@@ -11,6 +11,7 @@
 INCLUDEPATH += ../QTfrontend/util
 INCLUDEPATH += ../misc/physfs/src
 INCLUDEPATH += ../misc/physfs/extras
+INCLUDEPATH += ../project_files/frontlib
 
 DESTDIR = ../bin
 
@@ -107,6 +108,7 @@
     ../QTfrontend/model/playerslistmodel.h \
     ../QTfrontend/util/LibavInteraction.h \
     ../QTfrontend/util/FileEngine.h \
+    ../QTfrontend/util/frontlibpoller.h \
     ../QTfrontend/ui/dialog/bandialog.h \
     ../QTfrontend/ui/widget/keybinder.h
 
@@ -199,6 +201,7 @@
     ../QTfrontend/model/playerslistmodel.cpp \
     ../QTfrontend/util/LibavInteraction.cpp \
     ../QTfrontend/util/FileEngine.cpp \
+    ../QTfrontend/util/frontlibpoller.cpp \
     ../QTfrontend/ui/dialog/bandialog.cpp \
     ../QTfrontend/ui/widget/keybinder.cpp
 
@@ -235,7 +238,7 @@
 
 RESOURCES += ../QTfrontend/hedgewars.qrc
 
-LIBS += -L../bin -lphysfs
+LIBS += -L../bin -lfrontlib -lphysfs
 
 macx {
     QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6