Ticket #1504: 0ad-multiplayer-lobby-v30-06-2012.diff

File 0ad-multiplayer-lobby-v30-06-2012.diff, 68.7 KB (added by Badmadblacksad-, 11 months ago)

improve user interface

  • build/premake/extern_libs4.lua

     
    252252            }) 
    253253        end, 
    254254    }, 
     255    gloox = { 
     256        compile_settings = function() 
     257            add_default_include_paths("gloox") 
     258        end, 
     259        link_settings = function() 
     260            add_default_links({ 
     261                win_names  = { "gloox" }, 
     262                unix_names = { "gloox" }, 
     263            }) 
     264        end, 
     265    }, 
    255266    cxxtest = { 
    256267        compile_settings = function() 
    257268            add_default_include_paths("cxxtest") 
  • build/premake/premake4.lua

     
    486486 
    487487 
    488488    source_dirs = { 
     489    "lobby", 
     490    } 
     491    extern_libs = { 
     492    "spidermonkey", 
     493    "gloox", 
     494    } 
     495    setup_static_lib_project("lobby", source_dirs, extern_libs, {}) 
     496 
     497 
     498    source_dirs = { 
    489499        "simulation2", 
    490500        "simulation2/components", 
    491501        "simulation2/helpers", 
     
    705715    "libcurl", 
    706716 
    707717    "valgrind", 
     718 
     719    "gloox", 
    708720} 
    709721 
    710722if not os.is("windows") and not _OPTIONS["android"] and not os.is("macosx") then 
  • source/ps/GameSetup/GameSetup.cpp

     
    9191#include "network/NetServer.h" 
    9292#include "network/NetClient.h" 
    9393 
     94#include "lobby/XmppClient.h" 
     95 
    9496#include "ps/Pyrogenesis.h" // psSetLogDir 
    9597#include "ps/GameSetup/Atlas.h" 
    9698#include "ps/GameSetup/GameSetup.h" 
     
    653655{ 
    654656    EndGame(); 
    655657 
     658    SAFE_DELETE(g_XmppClient); 
     659 
    656660    ShutdownPs(); // Must delete g_GUI before g_ScriptingHost 
    657661 
    658662    in_reset_handlers(); 
     
    972976 
    973977    ogl_WarnIfError(); 
    974978 
     979  if (args.Has("looping")) 
     980  { 
     981    InitPs(true, L"page_multiplayerlobby.xml", JSVAL_VOID); 
     982    return; 
     983  } 
     984 
    975985    try 
    976986    { 
    977987        if (!Autostart(args)) 
  • source/gui/COList.h

     
     1#ifndef INCLUDED_COLIST 
     2#define INCLUDED_COLIST 
     3 
     4//-------------------------------------------------------- 
     5//  Includes / Compiler directives 
     6//-------------------------------------------------------- 
     7#include "GUI.h" 
     8#include "CList.h" 
     9 
     10//-------------------------------------------------------- 
     11//  Macros 
     12//-------------------------------------------------------- 
     13 
     14//-------------------------------------------------------- 
     15//  Types 
     16//-------------------------------------------------------- 
     17 
     18//-------------------------------------------------------- 
     19//  Declarations 
     20//-------------------------------------------------------- 
     21 
     22struct ObjectDef 
     23{ 
     24  CColor m_TextColor; 
     25  CStr m_Id; 
     26  int m_Width; 
     27  CStrW m_Heading; 
     28 
     29}; 
     30 
     31/** 
     32 *  Todo : add description 
     33 * 
     34 */ 
     35class COList : public CList 
     36{ 
     37  GUI_OBJECT(COList) 
     38 
     39public: 
     40    COList(); 
     41 
     42protected: 
     43    void SetupText(); 
     44    void HandleMessage(SGUIMessage &Message); 
     45 
     46    /** 
     47     * Handle the \<item\> tag. 
     48     */ 
     49    virtual bool HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile); 
     50 
     51    void DrawList(const int &selected, const CStr& _sprite, 
     52                    const CStr& _sprite_selected, const CStr& _textcolor); 
     53 
     54    virtual CRect GetListRect() const { 
     55        return m_CachedActualSize + CRect(0, m_HeadingHeight, 0, 0); 
     56 
     57                CRect(m_CachedActualSize.left, 
     58                                 m_CachedActualSize.top+m_HeadingHeight, 
     59                                 m_CachedActualSize.right, 
     60                                 m_CachedActualSize.bottom); } 
     61 
     62    std::vector<ObjectDef> m_ObjectsDefs; 
     63 
     64private: 
     65    float m_HeadingHeight; 
     66 
     67}; 
     68 
     69#endif // INCLUDED_COLIST 
  • source/gui/scripting/ScriptFunctions.cpp

     
    4343#include "ps/UserReport.h" 
    4444#include "ps/GameSetup/Atlas.h" 
    4545#include "ps/GameSetup/Config.h" 
     46#include "ps/ConfigDB.h" 
    4647#include "tools/atlas/GameInterface/GameLoop.h" 
     48#include "lobby/XmppClient.h" 
    4749 
    4850#include "simulation2/Simulation2.h" 
    4951#include "simulation2/components/ICmpAIManager.h" 
     
    556558    g_Game->GetTurnManager()->RewindTimeWarp(); 
    557559} 
    558560 
     561/* Begin lobby related functions */ 
     562 
     563void StartXmppClient(void* cbdata, std::string sUsername, std::string sPassword, std::string sRoom, std::string sNick) 
     564{ 
     565    CGUIManager* guiManager = static_cast<CGUIManager*> (cbdata); 
     566 
     567    ENSURE(!g_XmppClient); 
     568 
     569    g_XmppClient = new XmppClient(guiManager->GetScriptInterface(), sUsername, sPassword, sRoom, sNick); 
     570} 
     571 
     572void StartRegisterXmppClient(void* cbdata, std::string sUsername, std::string sPassword) 
     573{ 
     574    CGUIManager* guiManager = static_cast<CGUIManager*> (cbdata); 
     575 
     576    ENSURE(!g_XmppClient); 
     577 
     578    g_XmppClient = new XmppClient(guiManager->GetScriptInterface(), sUsername, sPassword, "", "", true); 
     579} 
     580 
     581void StopXmppClient(void* UNUSED(cbdata)) 
     582{ 
     583    ENSURE(g_XmppClient); 
     584    SAFE_DELETE(g_XmppClient); 
     585} 
     586 
     587void ConnectXmppClient(void* UNUSED(cbdata)) 
     588{ 
     589    ENSURE(g_XmppClient); 
     590    g_XmppClient->connect(); 
     591} 
     592 
     593void DisconnectXmppClient(void* UNUSED(cbdata)) 
     594 
     595    ENSURE(g_XmppClient); 
     596    g_XmppClient->disconnect(); 
     597} 
     598 
     599void RecvXmppClient(void* UNUSED(cbdata)) 
     600{ 
     601    if(!g_XmppClient) 
     602        return; 
     603    g_XmppClient->recv(); 
     604} 
     605 
     606void SendGetGameList(void* UNUSED(cbdata)) 
     607{ 
     608    if(!g_XmppClient) 
     609        return; 
     610    g_XmppClient->SendIqGetGameList(); 
     611} 
     612 
     613void SendRegisterGame(void* UNUSED(cbdata), CScriptVal data) 
     614{ 
     615    if(!g_XmppClient) 
     616        return; 
     617    g_XmppClient->SendIqRegisterGame(data); 
     618} 
     619 
     620void SendUnregisterGame(void* UNUSED(cbdata), std::string name) 
     621{ 
     622    if(!g_XmppClient) 
     623        return; 
     624    g_XmppClient->SendIqUnregisterGame(name); 
     625} 
     626 
     627CScriptVal GetPlayerList(void* UNUSED(cbdata)) 
     628{ 
     629    if(!g_XmppClient) 
     630        return CScriptVal(); 
     631 
     632    CScriptValRooted playerList = g_XmppClient->GUIGetPlayerList(); 
     633 
     634    return playerList.get(); 
     635} 
     636 
     637CScriptVal GetGameList(void* UNUSED(cbdata)) 
     638{ 
     639    if(!g_XmppClient) 
     640        return CScriptVal(); 
     641 
     642    CScriptValRooted gameList = g_XmppClient->GUIGetGameList(); 
     643 
     644    return gameList.get(); 
     645} 
     646 
     647CScriptVal LobbyGuiPollMessage(void* UNUSED(cbdata)) 
     648{ 
     649    if(!g_XmppClient) 
     650        return CScriptVal(); 
     651 
     652    CScriptValRooted poll = g_XmppClient->GuiPollMessage(); 
     653 
     654    return poll.get(); 
     655} 
     656 
     657void LobbySendMessage(void* UNUSED(cbdata), std::string message) 
     658{ 
     659    if(!g_XmppClient) 
     660        return; 
     661 
     662    g_XmppClient->SendMUCMessage(message); 
     663} 
     664 
     665std::string GetDefaultLobbyPlayerUsername(void* UNUSED(cbdata)) 
     666{ 
     667    std::string username; 
     668    CFG_GET_USER_VAL("lobby.login", String, username); 
     669    return username; 
     670} 
     671 
     672std::string GetDefaultLobbyPlayerPassword(void* UNUSED(cbdata)) 
     673{ 
     674    std::string password; 
     675    CFG_GET_USER_VAL("lobby.password", String, password); 
     676    return password; 
     677} 
     678 
     679void SetDefaultLobbyPlayerPair(void * UNUSED(cbdata), std::string username, std::string password) 
     680{ 
     681    g_ConfigDB.CreateValue(CFG_USER, "lobby.login")->m_String = username; 
     682    g_ConfigDB.CreateValue(CFG_USER, "lobby.password")->m_String = password; 
     683    g_ConfigDB.WriteFile(CFG_USER); 
     684} 
     685 
     686/* End lobby related functions */ 
     687 
    559688void QuickSave(void* UNUSED(cbdata)) 
    560689{ 
    561690    g_Game->GetTurnManager()->QuickSave(); 
     
    648777    scriptInterface.RegisterFunction<void, unsigned int, &EnableTimeWarpRecording>("EnableTimeWarpRecording"); 
    649778    scriptInterface.RegisterFunction<void, &RewindTimeWarp>("RewindTimeWarp"); 
    650779    scriptInterface.RegisterFunction<void, bool, &SetBoundingBoxDebugOverlay>("SetBoundingBoxDebugOverlay"); 
     780 
     781    // Lobby functions 
     782    scriptInterface.RegisterFunction<void, std::string, std::string, std::string, std::string, &StartXmppClient>("StartXmppClient"); 
     783    scriptInterface.RegisterFunction<void, std::string, std::string, &StartRegisterXmppClient>("StartRegisterXmppClient"); 
     784    scriptInterface.RegisterFunction<void, &StopXmppClient>("StopXmppClient"); 
     785    scriptInterface.RegisterFunction<void, &ConnectXmppClient>("ConnectXmppClient"); 
     786    scriptInterface.RegisterFunction<void, &DisconnectXmppClient>("DisconnectXmppClient"); 
     787    scriptInterface.RegisterFunction<void, &RecvXmppClient>("RecvXmppClient"); 
     788    scriptInterface.RegisterFunction<void, &SendGetGameList>("SendGetGameList"); 
     789    scriptInterface.RegisterFunction<void, CScriptVal, &SendRegisterGame>("SendRegisterGame"); 
     790    scriptInterface.RegisterFunction<void, std::string, &SendUnregisterGame>("SendUnregisterGame"); 
     791    scriptInterface.RegisterFunction<CScriptVal, &GetPlayerList>("GetPlayerList"); 
     792    scriptInterface.RegisterFunction<CScriptVal, &GetGameList>("GetGameList"); 
     793    scriptInterface.RegisterFunction<CScriptVal, &LobbyGuiPollMessage>("LobbyGuiPollMessage"); 
     794    scriptInterface.RegisterFunction<void, std::string, &LobbySendMessage>("LobbySendMessage"); 
     795    scriptInterface.RegisterFunction<std::string, &GetDefaultLobbyPlayerUsername>("GetDefaultLobbyPlayerUsername"); 
     796    scriptInterface.RegisterFunction<std::string, &GetDefaultLobbyPlayerPassword>("GetDefaultLobbyPlayerPassword"); 
     797    scriptInterface.RegisterFunction<void, std::string, std::string, &SetDefaultLobbyPlayerPair>("SetDefaultLobbyPlayerPair"); 
    651798} 
  • source/gui/CList.h

     
    8686     * Sets up text, should be called every time changes has been 
    8787     * made that can change the visual. 
    8888     */ 
    89     void SetupText(); 
     89    virtual void SetupText(); 
    9090 
    9191    /** 
    9292     * @see IGUIObject#HandleMessage() 
     
    121121 
    122122    // Extended drawing interface, this is so that classes built on the this one 
    123123    //  can use other sprite names. 
    124     void DrawList(const int &selected, const CStr& _sprite,  
     124    virtual void DrawList(const int &selected, const CStr& _sprite, 
    125125                  const CStr& _sprite_selected, const CStr& _textcolor); 
    126126 
    127127    // Get the area of the list. This is so that i can easily be changed, like in CDropDown 
  • source/gui/CGUI.cpp

     
    3535#include "CRadioButton.h" 
    3636#include "CInput.h" 
    3737#include "CList.h" 
     38#include "COList.h" 
    3839#include "CDropDown.h" 
    3940#include "CProgressBar.h" 
    4041#include "CTooltip.h" 
     
    442443    AddObjectType("minimap",        &CMiniMap::ConstructObject); 
    443444    AddObjectType("input",          &CInput::ConstructObject); 
    444445    AddObjectType("list",           &CList::ConstructObject); 
     446    AddObjectType("olist",          &COList::ConstructObject); 
    445447    AddObjectType("dropdown",       &CDropDown::ConstructObject); 
    446448    AddObjectType("tooltip",        &CTooltip::ConstructObject); 
    447449} 
  • source/gui/IGUIObject.h

     
    424424     * have any additional children (and this function should never be called). 
    425425     */ 
    426426    virtual bool HandleAdditionalChildren(const XMBElement& UNUSED(child),  
    427                                           CXeromyces* UNUSED(pFile)) { return false; } 
     427                                            CXeromyces* UNUSED(pFile)) { return false; } 
    428428 
    429429    /** 
    430430     * Cached size, real size m_Size is actually dependent on resolution 
  • source/gui/COList.cpp

     
     1#include "COList.h" 
     2 
     3#include "ps/CLogger.h" 
     4 
     5COList::COList() : CList(),m_HeadingHeight(30.f) 
     6{ 
     7    AddSetting(GUIST_CGUISpriteInstance,    "sprite_heading"); 
     8} 
     9 
     10void COList::SetupText() 
     11{ 
     12    if (!GetGUI()) 
     13        return; 
     14 
     15    CGUIList *pList; 
     16    GUI<CGUIList>::GetSettingPointer(this, "list_ip", pList); 
     17 
     18    //ENSURE(m_GeneratedTexts.size()>=1); 
     19 
     20    m_ItemsYPositions.resize( pList->m_Items.size()+1 ); 
     21 
     22    // Delete all generated texts. Some could probably be saved, 
     23    //  but this is easier, and this function will never be called 
     24    //  continuously, or even often, so it'll probably be okay. 
     25    std::vector<SGUIText*>::iterator it; 
     26    for (it=m_GeneratedTexts.begin(); it!=m_GeneratedTexts.end(); ++it) 
     27    { 
     28        if (*it) 
     29            delete *it; 
     30    } 
     31    m_GeneratedTexts.clear(); 
     32 
     33    CStrW font; 
     34    if (GUI<CStrW>::GetSetting(this, "font", font) != PSRETURN_OK || font.empty()) 
     35        // Use the default if none is specified 
     36        // TODO Gee: (2004-08-14) Don't define standard like this. Do it with the default style. 
     37        font = L"default"; 
     38 
     39    //CGUIString caption; 
     40    bool scrollbar; 
     41    //GUI<CGUIString>::GetSetting(this, "caption", caption); 
     42    GUI<bool>::GetSetting(this, "scrollbar", scrollbar); 
     43 
     44    float width = GetListRect().GetWidth(); 
     45    // remove scrollbar if applicable 
     46    if (scrollbar && GetScrollBar(0).GetStyle()) 
     47        width -= GetScrollBar(0).GetStyle()->m_Width; 
     48 
     49    float buffer_zone=0.f; 
     50    GUI<float>::GetSetting(this, "buffer_zone", buffer_zone); 
     51 
     52 
     53    for (unsigned int c=0; c<m_ObjectsDefs.size(); ++c) 
     54    { 
     55        SGUIText *text = new SGUIText(); 
     56        CGUIString gui_string; 
     57        gui_string.SetValue(m_ObjectsDefs[c].m_Heading); 
     58        *text = GetGUI()->GenerateText(gui_string, font, width, buffer_zone, this); 
     59        AddText(text); 
     60    } 
     61 
     62 
     63    // Generate texts 
     64    float buffered_y = 0.f; 
     65 
     66    for (int i=0; i<(int)pList->m_Items.size(); ++i) 
     67    { 
     68        m_ItemsYPositions[i] = buffered_y; 
     69        for (unsigned int c=0; c<m_ObjectsDefs.size(); ++c) 
     70        { 
     71            CGUIList * pList_c; 
     72            GUI<CGUIList>::GetSettingPointer(this, m_ObjectsDefs[c].m_Id, pList_c); 
     73            SGUIText *text = new SGUIText(); 
     74            *text = GetGUI()->GenerateText(pList_c->m_Items[i], font, width, buffer_zone, this); 
     75            if (c==0) 
     76                buffered_y += text->m_Size.cy; 
     77            AddText(text); 
     78        } 
     79    } 
     80 
     81    m_ItemsYPositions[pList->m_Items.size()] = buffered_y; 
     82 
     83    //if (! scrollbar) 
     84    //  CalculateTextPosition(m_CachedActualSize, m_TextPos, *m_GeneratedTexts[0]); 
     85 
     86    // Setup scrollbar 
     87    if (scrollbar) 
     88    { 
     89        GetScrollBar(0).SetScrollRange( m_ItemsYPositions.back() ); 
     90        GetScrollBar(0).SetScrollSpace( GetListRect().GetHeight() ); 
     91 
     92        CRect rect = GetListRect(); 
     93        GetScrollBar(0).SetX( rect.right ); 
     94        GetScrollBar(0).SetY( rect.top ); 
     95        GetScrollBar(0).SetZ( GetBufferedZ() ); 
     96        GetScrollBar(0).SetLength( rect.bottom - rect.top ); 
     97    } 
     98} 
     99 
     100void COList::HandleMessage(SGUIMessage &Message) 
     101{ 
     102    CList::HandleMessage(Message); 
     103//  switch (Message.type) 
     104//  { 
     105//  case GUIM_SETTINGS_UPDATED: 
     106//      if (Message.value.Find("list_") != -1) 
     107//      { 
     108//          SetupText(); 
     109//      } 
     110//  } 
     111} 
     112 
     113bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile) 
     114{ 
     115    int elmt_item = pFile->GetElementID("item"); 
     116    int elmt_heading = pFile->GetElementID("heading"); 
     117    int elmt_def = pFile->GetElementID("def"); 
     118 
     119    if (child.GetNodeName() == elmt_item) 
     120    { 
     121        AddItem(child.GetText().FromUTF8(), child.GetText().FromUTF8()); 
     122        return true; 
     123    } 
     124    else if (child.GetNodeName() == elmt_heading) 
     125    { 
     126        CStrW text (child.GetText().FromUTF8()); 
     127 
     128        return true; 
     129    } 
     130    else if (child.GetNodeName() == elmt_def) 
     131    { 
     132        ObjectDef oDef; 
     133 
     134        XMBAttributeList attributes = child.GetAttributes(); 
     135        for (int i=0; i<attributes.Count; ++i) 
     136        { 
     137            XMBAttribute attr = attributes.Item(i); 
     138            CStr attr_name (pFile->GetAttributeString(attr.Name)); 
     139            CStr attr_value (attr.Value); 
     140 
     141            if (attr_name == "color") 
     142            { 
     143                CColor color; 
     144                if (!GUI<CColor>::ParseString(attr_value.FromUTF8(), color)) 
     145                    LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str()); 
     146                else oDef.m_TextColor = color; 
     147            } 
     148            else if (attr_name == "id") 
     149            { 
     150                oDef.m_Id = "list_"+attr_value; 
     151            } 
     152            else if (attr_name == "width") 
     153            { 
     154                int width; 
     155                if (!GUI<int>::ParseString(attr_value.FromUTF8(), width)) 
     156                    LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str()); 
     157                else 
     158                    oDef.m_Width = width; 
     159            } 
     160            else if (attr_name == "heading") 
     161            { 
     162                oDef.m_Heading = attr_value.FromUTF8(); 
     163            } 
     164 
     165        } 
     166 
     167        m_ObjectsDefs.push_back(oDef); 
     168 
     169        AddSetting(GUIST_CGUIList, oDef.m_Id); 
     170        SetupText(); 
     171 
     172        return true; 
     173    } 
     174    else 
     175    { 
     176        return false; 
     177    } 
     178} 
     179 
     180void COList::DrawList(const int &selected, 
     181                     const CStr& _sprite, 
     182                     const CStr& _sprite_selected, 
     183                     const CStr& _textcolor) 
     184{ 
     185    float bz = GetBufferedZ(); 
     186 
     187    // First call draw on ScrollBarOwner 
     188    bool scrollbar; 
     189    GUI<bool>::GetSetting(this, "scrollbar", scrollbar); 
     190 
     191    if (scrollbar) 
     192    { 
     193        // Draw scrollbar 
     194        IGUIScrollBarOwner::Draw(); 
     195    } 
     196 
     197    if (GetGUI()) 
     198    { 
     199        CRect rect = GetListRect(); 
     200 
     201        CGUISpriteInstance *sprite=NULL, *sprite_selectarea=NULL; 
     202        int cell_id; 
     203        GUI<CGUISpriteInstance>::GetSettingPointer(this, _sprite, sprite); 
     204        GUI<CGUISpriteInstance>::GetSettingPointer(this, _sprite_selected, sprite_selectarea); 
     205        GUI<int>::GetSetting(this, "cell_id", cell_id); 
     206 
     207        CGUIList *pList; 
     208        GUI<CGUIList>::GetSettingPointer(this, "list_name", pList); 
     209 
     210        GetGUI()->DrawSprite(*sprite, cell_id, bz, rect); 
     211 
     212        float scroll=0.f; 
     213        if (scrollbar) 
     214        { 
     215            scroll = GetScrollBar(0).GetPos(); 
     216        } 
     217 
     218        if (selected != -1) 
     219        { 
     220            ENSURE(selected >= 0 && selected+1 < (int)m_ItemsYPositions.size()); 
     221 
     222            // Get rectangle of selection: 
     223            CRect rect_sel(rect.left, rect.top + m_ItemsYPositions[selected] - scroll, 
     224                                 rect.right, rect.top + m_ItemsYPositions[selected+1] - scroll); 
     225 
     226            if (rect_sel.top <= rect.bottom && 
     227                rect_sel.bottom >= rect.top) 
     228            { 
     229                if (rect_sel.bottom > rect.bottom) 
     230                    rect_sel.bottom = rect.bottom; 
     231                if (rect_sel.top < rect.top) 
     232                    rect_sel.top = rect.top; 
     233 
     234                if (scrollbar) 
     235                { 
     236                    // Remove any overlapping area of the scrollbar. 
     237                    if (rect_sel.right > GetScrollBar(0).GetOuterRect().left && 
     238                        rect_sel.right <= GetScrollBar(0).GetOuterRect().right) 
     239                        rect_sel.right = GetScrollBar(0).GetOuterRect().left; 
     240 
     241                    if (rect_sel.left >= GetScrollBar(0).GetOuterRect().left && 
     242                        rect_sel.left < GetScrollBar(0).GetOuterRect().right) 
     243                        rect_sel.left = GetScrollBar(0).GetOuterRect().right; 
     244                } 
     245 
     246                GetGUI()->DrawSprite(*sprite_selectarea, cell_id, bz+0.05f, rect_sel); 
     247            } 
     248        } 
     249 
     250        CColor color; 
     251        GUI<CColor>::GetSetting(this, _textcolor, color); 
     252 
     253        CGUISpriteInstance *sprite_heading=NULL; 
     254        GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_heading", sprite_heading); 
     255        CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right, 
     256                                        m_CachedActualSize.top + m_HeadingHeight); 
     257        GetGUI()->DrawSprite(*sprite_heading, cell_id, bz, rect_head); 
     258 
     259        float xpos = 0; 
     260        for (unsigned int def=0; def< m_ObjectsDefs.size(); ++def) 
     261        { 
     262            DrawText(def, color, m_CachedActualSize.TopLeft() + CPos(xpos, 4), bz+0.1f, rect_head); 
     263            xpos += m_ObjectsDefs[def].m_Width; 
     264        } 
     265 
     266        for (int i=0; i<(int)pList->m_Items.size(); ++i) 
     267        { 
     268            if (m_ItemsYPositions[i+1] - scroll < 0 || 
     269                m_ItemsYPositions[i] - scroll > rect.GetHeight()) 
     270                continue; 
     271 
     272            // Clipping area (we'll have to substract the scrollbar) 
     273            CRect cliparea = GetListRect(); 
     274 
     275            if (scrollbar) 
     276            { 
     277                if (cliparea.right > GetScrollBar(0).GetOuterRect().left && 
     278                    cliparea.right <= GetScrollBar(0).GetOuterRect().right) 
     279                    cliparea.right = GetScrollBar(0).GetOuterRect().left; 
     280 
     281                if (cliparea.left >= GetScrollBar(0).GetOuterRect().left && 
     282                    cliparea.left < GetScrollBar(0).GetOuterRect().right) 
     283                    cliparea.left = GetScrollBar(0).GetOuterRect().right; 
     284            } 
     285 
     286            xpos = 0; 
     287            for (unsigned int def=0; def< m_ObjectsDefs.size(); ++def) 
     288            { 
     289                DrawText(m_ObjectsDefs.size() * (i+/*Heading*/1) + def, m_ObjectsDefs[def].m_TextColor, rect.TopLeft() + CPos(xpos, -scroll + m_ItemsYPositions[i]), bz+0.1f, cliparea); 
     290                xpos += m_ObjectsDefs[def].m_Width; 
     291            } 
     292        } 
     293    } 
     294} 
  • source/tools/XpartaMuPP/XpartaMuPP.py

     
     1#!/usr/bin/env python3 
     2# -*- coding: utf-8 -*- 
     3 
     4""" 
     5    XpartaMuPP by : 
     6    Badmadblacksad 
     7    .. 
     8    For : 0ad 
     9    License : GPL 
     10""" 
     11 
     12import sys 
     13import logging 
     14import time 
     15from optparse import OptionParser 
     16 
     17import sleekxmpp 
     18from sleekxmpp.stanza import Iq 
     19from sleekxmpp.stanza import * 
     20from sleekxmpp.xmlstream import ElementBase, register_stanza_plugin, ET 
     21from sleekxmpp.xmlstream.handler import Callback 
     22from sleekxmpp.xmlstream.matcher import StanzaPath 
     23 
     24from xml.dom.minidom import Document 
     25 
     26## Configuration ## 
     27configDEMOModOn = False  
     28## !Configuration ## 
     29 
     30class BasicGameList(ElementBase): 
     31  name = 'query' 
     32  namespace = 'jabber:iq:gamelist' 
     33  interfaces = set(('game', 'command')) 
     34  sub_interfaces = interfaces 
     35  plugin_attrib = 'gamelist' 
     36 
     37  def addGame(self, name, ip, mapName, mapSize, victoryCondition, nbp, tnbp): 
     38    itemXml = ET.Element("game", {"name":name, "ip":ip, "nbp":nbp, "tnbp":tnbp, "mapName":mapName, "mapSize":mapSize, "victoryCondition":victoryCondition}) 
     39    self.xml.append(itemXml) 
     40 
     41  def getGame(self): 
     42    game = self.xml.find('{%s}game' % self.namespace) 
     43    return game.get("name"), game.get("ip"), game.get("mapName"), game.get("mapSize"), game.get("victoryCondition"), game.get("nbp"), game.get("tnbp")    
     44 
     45  def getCommand(self): 
     46    command = self.xml.find('{%s}command' % self.namespace) 
     47    return command 
     48 
     49class XpartaMuPP(sleekxmpp.ClientXMPP): 
     50  """ 
     51  A simple game list provider 
     52  """ 
     53 
     54  def __init__(self, sjid, password, room, nick): 
     55    sleekxmpp.ClientXMPP.__init__(self, sjid, password) 
     56    self.sjid = sjid 
     57    self.room = room 
     58    self.nick = nick 
     59 
     60    # Game management 
     61    self.m_gameList = {} 
     62     
     63    #DEMO 
     64    if configDEMOModOn: 
     65      self.addGame("666.666.666.666", "Unplayable map", "666.666.666.666", "Serengeti", "128", "gold rush", "4", "4") 
     66      self.addGame("666.666.666.667", "Unreachale liberty", "666.666.666.667", "oasis", "256", "conquest", "2", "4") 
     67      #for i in range(50): 
     68      #  self.addGame("666.666.666."+str(i), "X"+str(i), "666.666.666."+str(i), "Oasis", "large", "conquest", "1", "4")    
     69 
     70    register_stanza_plugin(Iq, BasicGameList) 
     71    self.register_handler(Callback('Iq Gamelist', 
     72                                       StanzaPath('iq/gamelist'), 
     73                                       self.iqhandler, 
     74                                       instream=True)) 
     75 
     76    self.add_event_handler("session_start", self.start) 
     77    self.add_event_handler("message", self.message) 
     78    self.add_event_handler("muc::%s::got_online" % self.room, self.muc_online) 
     79    self.add_event_handler("muc::%s::got_offline" % self.room, self.muc_offline) 
     80 
     81  def start(self, event): 
     82    """ 
     83    Process the session_start event 
     84    """ 
     85    self.plugin['xep_0045'].joinMUC(self.room, self.nick) 
     86 
     87    self.send_presence() 
     88    self.get_roster() 
     89    logging.info("xpartamupp started") 
     90 
     91    #DEMO 
     92    self.DEMOrequestGameList() 
     93    #self.DEMOregisterGame() 
     94 
     95  def message(self, msg): 
     96    """ 
     97    Process incoming message stanzas 
     98    """ 
     99    if msg['type'] == 'chat': 
     100      msg.reply("Thanks for sending\n%(body)s" % msg).send() 
     101      logging.comm("receive message"+msg['body']) 
     102 
     103  def muc_online(self, presence): 
     104    """ 
     105    Process presence stanza from a chat room.  
     106    """ 
     107    if presence['muc']['nick'] != self.nick: 
     108      self.send_message(mto=presence['from'], mbody="Hello %s, welcome in the 0ad alpha chatroom. Polishes your weapons and get ready to fight!" %(presence['muc']['nick']), mtype='') 
     109 
     110  def muc_offline(self, presence): 
     111    """ 
     112    Process presence stanza from a chat room.  
     113    """ 
     114    if presence['muc']['nick'] != self.nick: 
     115      self.removeGame(presence['muc']['jid'].bare) 
     116 
     117  def iqhandler(self, iq): 
     118    """ 
     119    Handle the custom <gamelist> stanza 
     120    TODO: This method should be very robust because 
     121    we could receive anything 
     122    """ 
     123    if iq['type'] == 'error': 
     124      logging.error('iqhandler error' + iq['error']['condition']) 
     125      #self.disconnect() 
     126    elif iq['type'] == 'get': 
     127      """ 
     128      Request a gamelist 
     129      """ 
     130      self.sendGameList(iq['from']) 
     131    elif iq['type'] == 'result': 
     132      """ 
     133      Iq successfully received 
     134      """ 
     135      pass 
     136    elif iq['type'] == 'set': 
     137      """ 
     138      Register-update / unregister a game 
     139      """ 
     140      command = iq['gamelist']['command'].text 
     141      if command == 'register': 
     142        try: 
     143          name, ip, mapName, mapSize, victoryCondition, nbp, tnbp = iq['gamelist']['game'] 
     144          logging.debug("ip " + ip) 
     145          self.addGame(iq['from'].bare,name,ip,mapName,mapSize,victoryCondition,nbp,tnbp) 
     146        except: 
     147          logging.error("Failed to process game data") 
     148      elif command == 'unregister': 
     149        self.removeGame(iq['from'].bare) 
     150 
     151  def sendGameList(self, to): 
     152    """ 
     153    Send a massive stanza with the whole game list 
     154    """ 
     155    stz = BasicGameList() 
     156    for k in self.m_gameList: 
     157      g = self.m_gameList[k] 
     158      stz.addGame(g['name'], g['ip'], g['mapName'], g['mapSize'], g['victoryCondition'], g['nbp'], g['tnbp']) 
     159    iq = self.Iq() 
     160    iq['type'] = 'result' 
     161    iq['to'] = to 
     162    iq.setPayload(stz) 
     163    try: 
     164      iq.send() 
     165    except: 
     166      logging.error("Failed to send game list") 
     167 
     168  def DEMOrequestGameList(self): 
     169    """ 
     170    Test function 
     171    """ 
     172    iq = self.Iq() 
     173    iq['type'] = 'get' 
     174    iq['gamelist']['field'] = 'x' 
     175    iq['to'] = self.boundjid.full 
     176    iq.send(now=True, block=False) 
     177    return True 
     178 
     179  def DEMOregisterGame(self): 
     180    """ 
     181    Test function 
     182    """ 
     183    stz = BasicGameList() 
     184    stz.addGame("DEMOregister","DEMOip","DEMOmap","","","","") 
     185    stz['command'] = 'register' 
     186    iq = self.Iq() 
     187    iq['type'] = 'set' 
     188    iq['to'] = self.boundjid.full 
     189    iq.setPayload(stz) 
     190    iq.send(now=True, block=False) 
     191    return True 
     192 
     193  # Game management 
     194 
     195  def addGame(self, sid, name, ip, mapName, mapSize, victoryCondition, nbp, tnbp): 
     196    game = { 'name':name, 'ip':ip, 'nbp':nbp, 'tnbp':tnbp, 'mapName':mapName, 'mapSize':mapSize, 'victoryCondition':victoryCondition }  
     197    self.m_gameList[sid] = game 
     198 
     199  def removeGame(self, sid): 
     200    if sid in self.m_gameList: 
     201      del self.m_gameList[sid] 
     202 
     203if __name__ == '__main__': 
     204  # Setup the command line arguments. 
     205  optp = OptionParser() 
     206 
     207  # Output verbosity options. 
     208  optp.add_option('-q', '--quiet', help='set logging to ERROR', 
     209                  action='store_const', dest='loglevel', 
     210                  const=logging.ERROR, default=logging.INFO) 
     211  optp.add_option('-d', '--debug', help='set logging to DEBUG', 
     212                  action='store_const', dest='loglevel', 
     213                  const=logging.DEBUG, default=logging.INFO) 
     214  optp.add_option('-v', '--verbose', help='set logging to COMM', 
     215                  action='store_const', dest='loglevel', 
     216                  const=5, default=logging.INFO) 
     217 
     218  # XpartaMuPP configuration options 
     219  optp.add_option('-m', '--domain', help='set xpartamupp domain', 
     220                  action='store', dest='xdomain', 
     221                  default="localhost") 
     222  optp.add_option('-l', '--login', help='set xpartamupp login', 
     223                  action='store', dest='xlogin', 
     224                  default="xpartamupp") 
     225  optp.add_option('-p', '--password', help='set xpartamupp password', 
     226                  action='store', dest='xpassword', 
     227                  default="XXXXXX") 
     228  optp.add_option('-n', '--nickname', help='set xpartamupp nickname', 
     229                  action='store', dest='xnickname', 
     230                  default="XpartaMuCC") 
     231  optp.add_option('-D', '--demo', help='set xpartamupp in DEMO mode (add a few fake games)', 
     232                  action='store_true', dest='xdemomode', 
     233                  default=False) 
     234 
     235  opts, args = optp.parse_args() 
     236 
     237  # Set DEMO mode 
     238  configDEMOModOn = opts.xdemomode 
     239 
     240  # Setup logging. 
     241  logging.basicConfig(level=opts.loglevel, 
     242                      format='%(levelname)-8s %(message)s') 
     243 
     244  # XpartaMuPP 
     245  xmpp = XpartaMuPP(opts.xlogin+'@'+opts.xdomain+'/CC', opts.xpassword, 'arena@conference.'+opts.xdomain, opts.xnickname) 
     246  xmpp.register_plugin('xep_0030') # Service Discovery 
     247  xmpp.register_plugin('xep_0004') # Data Forms 
     248  xmpp.register_plugin('xep_0045') # Multi-User Chat    # used 
     249  xmpp.register_plugin('xep_0060') # PubSub 
     250  xmpp.register_plugin('xep_0199') # XMPP Ping 
     251 
     252  if xmpp.connect(): 
     253    xmpp.process(threaded=False) 
     254  else: 
     255    logging.error("Unable to connect") 
     256 
  • source/tools/XpartaMuPP/mod_ipstamp.erl

    Property changes on: source/tools/XpartaMuPP/XpartaMuPP.py
    ___________________________________________________________________
    Added: svn:executable
       + *
    
     
     1 
     2-module(mod_ipstamp). 
     3 
     4-behaviour(gen_mod). 
     5 
     6-include("ejabberd.hrl"). 
     7 
     8-export([start/2, stop/1, on_filter_packet/1]). 
     9 
     10start(_Host, _Opts) -> 
     11    ?INFO_MSG("mod_ipip starting", []), 
     12    ejabberd_hooks:add(filter_packet, global, ?MODULE, on_filter_packet, 50), 
     13    ok. 
     14 
     15stop(_Host) -> 
     16    ejabberd_hooks:delete(filter_packet, global, ?MODULE, on_filter_packet, 50), 
     17    ok. 
     18 
     19on_filter_packet({From, To, Packet} = Input) -> 
     20    {_,STo,_,_,_,_,_} = To, 
     21    if STo == "xpartamupp" -> 
     22      {_,SElement,LPacketInfo,LPacketQuery} = Packet, 
     23      if SElement == "iq" ->  
     24        {_, SType} = lists:keyfind("type",1,LPacketInfo), 
     25        if SType == "set" -> 
     26      {_,_,LXmlns,LGame} = lists:keyfind("query",2,LPacketQuery), 
     27          {_,SXmlns} = lists:keyfind("xmlns",1,LXmlns), 
     28          if SXmlns == "jabber:iq:gamelist" -> 
     29            {_,_,_,LCommand} = lists:keyfind("command",2,LGame), 
     30            {_,SCommand} = lists:keyfind(xmlcdata,1,LCommand), 
     31            if SCommand == <<"register">> -> 
     32              {_,_,KGame,_} = lists:keyfind("game",2,LGame), 
     33              Info = ejabberd_sm:get_user_info("xpartamupp","localhost","CC"), 
     34              {ip, {Ploc, _Port}} = lists:keyfind(ip, 1, Info), 
     35              SIp = inet_parse:ntoa(Ploc), 
     36              ?INFO_MSG(string:concat("stamp ip: ",SIp), []), 
     37              {From,To,{xmlelement,"iq",LPacketInfo,[ 
     38                {xmlelement,"query",[{"xmlns","jabber:iq:gamelist"}],[ 
     39                  {xmlelement,"game",lists:keyreplace("ip",1,KGame,{"ip",SIp}),[]}, 
     40                  {xmlelement,"command",[],[{xmlcdata,<<"register">>}]} 
     41                  ] 
     42                } 
     43              ]}} 
     44            ; true -> Input 
     45            end  
     46          ; true -> Input 
     47          end 
     48        ; true -> Input 
     49        end 
     50      ; true -> Input 
     51      end 
     52    ; true -> Input  
     53    end. 
     54 
  • source/tools/XpartaMuPP/Makefile

     
     1include_dir = /usr/lib/ejabberd/include/ 
     2ebin_dir = /usr/lib/ejabberd/ebin/ 
     3 
     4module = mod_ipstamp.beam 
     5all : ${module} 
     6 
     7%.beam : %.erl 
     8    erlc -I ${include_dir} -pz ${ebin_dir} $< 
     9 
     10install :  
     11    mv ${module} ${ebin_dir} 
     12 
     13clean : 
     14    rm ${module} 
     15 
     16restart : 
     17    rm -f /var/log/ejabberd/ejabberd.log 
     18    /etc/init.d/ejabberd restart 
  • source/tools/XpartaMuPP/README

     
     1@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     2@@ Install ejabberd and the erlang compiler @@ 
     3@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     4# apt-get install ejabberd erlang-dev? 
     5 
     6Configure it 
     7# dpkg-reconfigure ejabberd  
     8set the domain name (e.g. localhost if you installed it on your development computer) 
     9and a login / password 
     10 
     11You should now be able to connect to this XMPP server using a normal XMPP client (e.g. Empathy). 
     12 
     13@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     14@@ Installation of the custom XMPP module @@ 
     15@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     16Go to it's source directory 
     17$ cd source/tools/XpartaMuPP 
     18 
     19Build and install it 
     20$ make 
     21# make install 
     22 
     23Tell ejabberd that you want it to load the module 
     24In /etc/ejabberd/ejabberd.cfg, add {mod_ipstamp, []} 
     25in the Modules list "Modules enabled in all ejabberd virtual hosts" 
     26 
     27Restart ejabberd 
     28# service ejabberd restart 
     29 
     30If something goes wrong read /var/log/ejabberd/ejabberd.log 
     31 
     32@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     33@@ Ejabberd administration @@ 
     34@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     35Go http://localhost:5280/admin and connect  
     36(the login looks like login@domain (e.g. adminjabber@localhost)) 
     37 
     38In "Acces rules" check that "register" is set to "[{allow,all}]" 
     39 
     40You can see the list of registered / connected users in 
     41"Virtual Hosts" >> domain name >> "users" 
     42 
     43You must manually add a new user for XpartaMuPP. 
     44Enter a login (use "xpartamupp" since that's what clients expect)  
     45and password, then press "Add user" 
     46 
     47@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     48@@ Run XpartaMuPP - XMPP Multiplayer Game Manager @@ 
     49@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
     50You need to have python 3 installed 
     51$ sudo apt-get install python3 
     52 
     53You also need the SleekXmpp Python library 
     54Go to to github and follow their instructions 
     55https://github.com/fritzy/SleekXMPP 
     56 
     57Then execute the following command to run the script with default options 
     58$ ./source/tools/XpartaMuPP.py 
     59 
     60or rather a similar command to run a properly configured program 
     61$ ./source/tools/XpartaMuPP.py --domain localhost --login xpartamupp --password XXXXXX --nickname XpartaMuCC 
     62 
     63Run ./source/tools/XpartaMuPP.py -h for the full list of options 
     64 
     65If everything is fine you should see something along these lines in your console 
     66<<<<  
     67INFO     Negotiating TLS 
     68INFO     Using SSL version: 3 
     69INFO     Node set to: xpartamupp@localhost/CC 
     70xpartamupp started 
     71<<<< 
     72 
     73Congratulations, you are running XpartaMuPP - the 0ad Multiplayer Game Manager. 
     74 
  • source/lobby/XmppClient.cpp

     
     1#include "precompiled.h" 
     2#include "XmppClient.h" 
     3#include "GameItemData.h" 
     4 
     5//debug 
     6#include <iostream> 
     7 
     8#include <sstream> 
     9 
     10//Gloox 
     11#include <gloox/rostermanager.h> 
     12#include <gloox/rosteritem.h> 
     13#include <gloox/error.h> 
     14 
     15//Game - script 
     16#include "scriptinterface/ScriptInterface.h" 
     17 
     18//Configuration 
     19#include "ps/ConfigDB.h" 
     20 
     21//global 
     22XmppClient *g_XmppClient = NULL; 
     23 
     24//debug 
     25#if 1 
     26#define DbgXMPP(x) 
     27#else 
     28#define DbgXMPP(x) std::cout << x << std::endl; 
     29#endif 
     30 
     31//utils 
     32std::string StanzaErrorToString(StanzaError& err) 
     33{ 
     34  std::string msg; 
     35#define CASE(X, Y) case X: return Y; 
     36  switch (err) 
     37  { 
     38    CASE(StanzaErrorBadRequest, "Bad request") 
     39    CASE(StanzaErrorConflict, "Player name already used") 
     40    CASE(StanzaErrorFeatureNotImplemented, "Feature not implemented") 
     41    CASE(StanzaErrorForbidden, "Forbidden") 
     42    CASE(StanzaErrorGone, "Recipient or server gone") 
     43    CASE(StanzaErrorInternalServerError, "Internal server error") 
     44    CASE(StanzaErrorItemNotFound, "Item not found") 
     45    CASE(StanzaErrorJidMalformed, "Jid malformed") 
     46    CASE(StanzaErrorNotAcceptable, "Not acceptable") 
     47    CASE(StanzaErrorNotAllowed, "Not allowed") 
     48    CASE(StanzaErrorNotAuthorized, "Not authorized") 
     49    CASE(StanzaErrorNotModified, "Not modified") 
     50    CASE(StanzaErrorPaymentRequired, "Payment required") 
     51    CASE(StanzaErrorRecipientUnavailable, "Recipient unavailable") 
     52    CASE(StanzaErrorRedirect, "Redirect") 
     53    CASE(StanzaErrorRegistrationRequired, "Registration required") 
     54    CASE(StanzaErrorRemoteServerNotFound, "Remote server not found") 
     55    CASE(StanzaErrorRemoteServerTimeout, "Remote server timeout") 
     56    CASE(StanzaErrorResourceConstraint, "Resource constraint") 
     57    CASE(StanzaErrorServiceUnavailable, "Service unavailable") 
     58    CASE(StanzaErrorSubscribtionRequired, "Subscribtion Required") 
     59    CASE(StanzaErrorUndefinedCondition, "Undefined condition") 
     60    CASE(StanzaErrorUnexpectedRequest, "Unexpected request") 
     61    CASE(StanzaErrorUnknownSender, "Unknown sender")  
     62    default: 
     63      return "Error undefined"; 
     64  } 
     65#undef CASE 
     66} 
     67 
     68XmppClient::XmppClient(ScriptInterface& scriptInterface, std::string sUsername, std::string sPassword, std::string sRoom, std::string sNick, bool regOpt) 
     69  : m_ScriptInterface(scriptInterface), _client(NULL), _mucRoom(NULL), _registration(NULL), _username(sUsername), _password(sPassword), _nick(sNick) 
     70{ 
     71  // Read lobby configuration from default.cfg 
     72  std::string sServer; 
     73  std::string sXpartamupp; 
     74  CFG_GET_USER_VAL("lobby.server", String, sServer); 
     75  CFG_GET_USER_VAL("lobby.xpartamupp", String, sXpartamupp); 
     76 
     77  _xpartamuppId = sXpartamupp+std::string("@")+sServer+std::string("/CC"); 
     78  JID clientJid(sUsername+std::string("@")+sServer+std::string("/0ad")); 
     79  JID roomJid(sRoom+std::string("@conference.")+sServer+std::string("/")+sNick); 
     80 
     81  // If we are connecting, use the full jid and a password 
     82  // If we are registering, only use the server name 
     83  if(!regOpt) 
     84    _client = new Client(clientJid, sPassword); 
     85  else 
     86    _client = new Client(sServer); 
     87 
     88  _client->registerConnectionListener( this ); 
     89  _client->setPresence(Presence::Available, -1); 
     90  _client->disco()->setVersion( "TestProg", "1.0" ); 
     91  _client->disco()->setIdentity( "client", "bot" ); 
     92  _client->setCompression(false); 
     93 
     94  _client->registerStanzaExtension( new GameListQuery() ); 
     95  _client->registerIqHandler( this, ExtGameListQuery); 
     96 
     97  _client->registerMessageHandler( this ); 
     98 
     99  StringList ca; 
     100  ca.push_back( "/path/to/cacert.crt" ); 
     101  _client->setCACerts( ca ); 
     102 
     103  // Uncomment to see the raw stanzas 
     104  //_client->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this ); 
     105 
     106  if (!regOpt) 
     107  { 
     108    // Create a Multi User Chat Room 
     109    _mucRoom = new MUCRoom(_client, roomJid, this, 0); 
     110    // Disable the history because its anoying 
     111    _mucRoom->setRequestHistory(0, MUCRoom::HistoryMaxStanzas); 
     112  } 
     113  else 
     114  { 
     115    // Registration 
     116    _registration = new Registration( _client ); 
     117    _registration->registerRegistrationHandler( this ); 
     118  } 
     119} 
     120 
     121XmppClient::~XmppClient() 
     122{ 
     123  DbgXMPP("XmppClient destroyed"); 
     124  delete _registration; 
     125  delete _mucRoom; 
     126  delete _client; 
     127} 
     128 
     129// Game - script 
     130ScriptInterface& XmppClient::GetScriptInterface() 
     131{ 
     132  return m_ScriptInterface; 
     133} 
     134 
     135//Network 
     136void XmppClient::connect() 
     137{ 
     138  _client->connect(false); 
     139} 
     140 
     141void XmppClient::disconnect() 
     142{ 
     143  _client->disconnect(); 
     144} 
     145 
     146void XmppClient::recv() 
     147{ 
     148  _client->recv(1); 
     149} 
     150 
     151/* 
     152 *  MUC Handlers 
     153 */ 
     154void XmppClient::handleMUCParticipantPresence(gloox::MUCRoom*, gloox::MUCRoomParticipant participant, const gloox::Presence& presence) 
     155 
     156  //std::string jid = participant.jid->full(); 
     157  std::string nick = participant.nick->resource(); 
     158  gloox::Presence::PresenceType presenceType = presence.presence(); 
     159  if (presenceType == Presence::Unavailable) 
     160  { 
     161    DbgXMPP(nick << " left the room"); 
     162    m_PlayerMap.erase(nick); 
     163  } 
     164  else 
     165  { 
     166    DbgXMPP(nick << " is in the room"); 
     167    m_PlayerMap[nick] = std::pair<std::string, int>(nick, (int)presenceType); 
     168  } 
     169  CreateSimpleMessage("system", "playerlist updated", "internal"); 
     170} 
     171 
     172void XmppClient::handleMUCMessage( MUCRoom*, const Message& msg, bool ) 
     173{ 
     174  DbgXMPP(msg.from().resource() << " said " << msg.body()); 
     175  std::string nick = msg.from().resource(); 
     176  std::string body = msg.body(); 
     177 
     178  CScriptValRooted message; 
     179  GetScriptInterface().Eval("({ 'type':'mucmessage'})", message); 
     180  GetScriptInterface().SetProperty(message.get(), "from", nick); 
     181  GetScriptInterface().SetProperty(message.get(), "text", body); 
     182  PushGuiMessage(message); 
     183} 
     184 
     185void XmppClient::handleMUCError(gloox::MUCRoom*, gloox::StanzaError err) 
     186{ 
     187  std::string msg = StanzaErrorToString(err); 
     188  CreateSimpleMessage("system", msg, "error"); 
     189} 
     190 
     191void XmppClient::handleMUCItems( MUCRoom * /*room*/, const Disco::ItemList& items ) 
     192{ 
     193  m_PlayerMap.clear(); 
     194 
     195  // Add the received items 
     196  Disco::ItemList::const_iterator it = items.begin(); 
     197  for( ; it != items.end(); ++it ) 
     198  { 
     199    std::string jid = (*it)->jid().full().c_str(); 
     200    std::string nick = (*it)->name().c_str(); 
     201    m_PlayerMap[nick] = std::pair<std::string, int>(nick, Presence::Available); 
     202    //printf( "%s -- %s is an item here\n", (*it)->jid().full().c_str(), (*it)->name().c_str() ); 
     203  } 
     204  CreateSimpleMessage("system", "playerlist updated", "internal"); 
     205} 
     206 
     207/* 
     208 *  Log (debug) Handler 
     209 */ 
     210void XmppClient::handleLog( LogLevel level, LogArea area, const std::string& message ) 
     211{ 
     212  std::cout << "log: level: " <<  level << ", area: " << area << ", message: " << message << std::endl; 
     213} 
     214 
     215/* 
     216 *  IQ Handler 
     217 */ 
     218bool XmppClient::handleIq( const IQ& iq ) 
     219{ 
     220  DbgXMPP("handleIq [" << iq.tag()->xml() << "]"); 
     221 
     222  if(iq.subtype() == gloox::IQ::Result) 
     223  { 
     224    const GameListQuery* q = iq.findExtension<GameListQuery>( ExtGameListQuery ); 
     225    if(q) 
     226    { 
     227      m_GameList.clear(); 
     228      std::list<GameItemData*>::const_iterator it = q->gameList().begin(); 
     229      for(; it != q->gameList().end(); ++it) 
     230      { 
     231        m_GameList.push_back(**it); 
     232      } 
     233      CreateSimpleMessage("system", "gamelist updated", "internal"); 
     234    } 
     235  } 
     236  else if(iq.subtype() == gloox::IQ::Error) 
     237  { 
     238    StanzaError err = iq.error()->error(); 
     239    std::string msg = StanzaErrorToString(err); 
     240    CreateSimpleMessage("system", msg, "error"); 
     241  } 
     242  else 
     243  { 
     244    CreateSimpleMessage("system", std::string("unknown subtype : ") + iq.tag()->name(), "error"); 
     245  } 
     246 
     247  return true; 
     248} 
     249 
     250/* 
     251 *  Connection Handlers 
     252 */ 
     253void XmppClient::onConnect() 
     254{ 
     255  if (_mucRoom) 
     256  { 
     257    CreateSimpleMessage("system", "connected"); 
     258    _mucRoom->join(); 
     259    //_mucRoom->getRoomInfo(); 
     260    _mucRoom->getRoomItems(); 
     261    SendIqGetGameList(); 
     262  } 
     263 
     264  if (_registration) 
     265  { 
     266    _registration->fetchRegistrationFields(); 
     267  } 
     268} 
     269 
     270void XmppClient::onDisconnect( ConnectionError e ) 
     271{ 
     272  // Make sure we properly leave the room so than 
     273  // everything work if we decide to come back later 
     274  if (_mucRoom) 
     275    _mucRoom->leave(); 
     276 
     277  if( e == ConnAuthenticationFailed ) 
     278    CreateSimpleMessage("system", "authentication failed", "error"); 
     279  else 
     280    CreateSimpleMessage("system", "disconnected"); 
     281 
     282  m_PlayerMap.clear(); 
     283  m_GameList.clear(); 
     284  CreateSimpleMessage("system", "playerlist updated", "internal"); 
     285  CreateSimpleMessage("system", "gamelist updated", "internal"); 
     286} 
     287 
     288bool XmppClient::onTLSConnect( const CertInfo& ) 
     289{ 
     290  return true; 
     291} 
     292 
     293/* 
     294 *  Requests 
     295 */ 
     296 
     297/* Request GameList from cloud */ 
     298void XmppClient::SendIqGetGameList() 
     299{ 
     300  JID xpartamuppJid(_xpartamuppId); 
     301 
     302  // Send IQ 
     303  IQ iq(gloox::IQ::Get, xpartamuppJid); 
     304  iq.addExtension( new GameListQuery() ); 
     305  DbgXMPP("SendIqGetGameList [" << iq.tag()->xml() << "]"); 
     306  _client->send(iq); 
     307} 
     308 
     309/* Register a game */ 
     310void XmppClient::SendIqRegisterGame(CScriptVal data) 
     311{ 
     312  JID xpartamuppJid(_xpartamuppId); 
     313 
     314  std::string name, mapName, mapSize, victoryCondition, nbp, tnbp; 
     315  GetScriptInterface().GetProperty(data.get(), "name", name); 
     316  GetScriptInterface().GetProperty(data.get(), "mapName", mapName); 
     317  GetScriptInterface().GetProperty(data.get(), "mapSize", mapSize); 
     318  GetScriptInterface().GetProperty(data.get(), "victoryCondition", victoryCondition); 
     319  GetScriptInterface().GetProperty(data.get(), "nbp", nbp); 
     320  GetScriptInterface().GetProperty(data.get(), "tnbp", tnbp); 
     321 
     322  // Send IQ 
     323  GameListQuery* g = new GameListQuery(); 
     324  g->m_command = "register"; 
     325  /* This "x" fake ip will be overwritten by the ip stamp XMPP module */ 
     326  GameItemData *pItemData = new GameItemData(name, "x"); 
     327  pItemData->m_mapName = mapName; 
     328  pItemData->m_mapSize = mapSize; 
     329  pItemData->m_victoryCondition = victoryCondition; 
     330  pItemData->m_nbp = nbp; 
     331  pItemData->m_tnbp = tnbp; 
     332  g->m_gameList.push_back( pItemData ); 
     333 
     334  IQ iq(gloox::IQ::Set, xpartamuppJid); 
     335  iq.addExtension( g ); 
     336  DbgXMPP("SendIqRegisterGame [" << iq.tag()->xml() << "]"); 
     337  _client->send(iq); 
     338} 
     339 
     340/* Unregister a game */ 
     341void XmppClient::SendIqUnregisterGame(std::string name) 
     342{ 
     343  JID xpartamuppJid(_xpartamuppId); 
     344 
     345  // Send IQ 
     346  GameListQuery* g = new GameListQuery(); 
     347  g->m_command = "unregister"; 
     348  g->m_gameList.push_back( new GameItemData(name) ); 
     349 
     350  IQ iq(gloox::IQ::Set, xpartamuppJid); 
     351  iq.addExtension( g ); 
     352  DbgXMPP("SendIqUnregisterGame [" << iq.tag()->xml() << "]"); 
     353  _client->send(iq); 
     354} 
     355 
     356/* 
     357 *  Registration 
     358 */ 
     359void XmppClient::handleRegistrationFields( const JID& /*from*/, int fields, std::string ) 
     360{ 
     361  RegistrationFields vals; 
     362  vals.username = _username; 
     363  vals.password = _password; 
     364  _registration->createAccount( fields, vals ); 
     365} 
     366 
     367void XmppClient::handleRegistrationResult( const JID& /*from*/, RegistrationResult result ) 
     368{ 
     369  if (result == gloox::RegistrationSuccess) 
     370  { 
     371    CreateSimpleMessage("system", "Registered"); 
     372  } 
     373  else 
     374  { 
     375    std::string msg; 
     376#define CASE(X, Y) case X: msg = Y; break; 
     377    switch(result) 
     378    { 
     379      CASE(RegistrationNotAcceptable, "Registration not acceptable") 
     380      CASE(RegistrationConflict, "Registration conflict") 
     381      CASE(RegistrationNotAuthorized, "Registration not authorized") 
     382      CASE(RegistrationBadRequest, "Registration bad request") 
     383      CASE(RegistrationForbidden, "Registration forbidden") 
     384      CASE(RegistrationRequired, "Registration required") 
     385      CASE(RegistrationUnexpectedRequest, "Registration unexpected request") 
     386      CASE(RegistrationNotAllowed, "Registration not allowed") 
     387      default: msg = "Registration unknown error"; 
     388    } 
     389#undef CASE 
     390    CreateSimpleMessage("system", msg, "error"); 
     391  } 
     392  disconnect(); 
     393} 
     394 
     395void XmppClient::handleAlreadyRegistered( const JID& /*from*/ ) 
     396{ 
     397  DbgXMPP("the account already exists"); 
     398} 
     399 
     400void XmppClient::handleDataForm( const JID& /*from*/, const DataForm& /*form*/ ) 
     401{ 
     402  DbgXMPP("dataForm received"); 
     403} 
     404 
     405void XmppClient::handleOOB( const JID& /*from*/, const OOB& /* oob */ ) 
     406{ 
     407  DbgXMPP("OOB registration requested"); 
     408} 
     409 
     410/** 
     411  * Message 
     412  */ 
     413void XmppClient::handleMessage( const Message& msg, MessageSession * /*session*/ ) 
     414{ 
     415  DbgXMPP("type " << msg.subtype() << ", subject " << msg.subject().c_str()  
     416    << ", message " << msg.body().c_str() << ", thread id " << msg.thread().c_str()); 
     417 
     418  std::string nick = msg.from().resource(); 
     419  std::string body = msg.body(); 
     420 
     421  CScriptValRooted message; 
     422  GetScriptInterface().Eval("({ 'type':'message'})", message); 
     423  GetScriptInterface().SetProperty(message.get(), "from", nick); 
     424  GetScriptInterface().SetProperty(message.get(), "text", body); 
     425  PushGuiMessage(message); 
     426} 
     427 
     428 
     429 
     430/* Requests from GUI */ 
     431CScriptValRooted XmppClient::GUIGetPlayerList() 
     432{ 
     433  CScriptValRooted playerList; 
     434  GetScriptInterface().Eval("({})", playerList); 
     435  for(std::map<std::string, std::pair<std::string, int> >::iterator it = m_PlayerMap.begin(); it != m_PlayerMap.end(); ++it) 
     436  { 
     437    CScriptValRooted player; 
     438    GetScriptInterface().Eval("({})", player); 
     439    GetScriptInterface().SetProperty(player.get(), "name", it->second.first.c_str()); 
     440    GetScriptInterface().SetProperty(player.get(), "presenceType", it->second.first); 
     441 
     442    GetScriptInterface().SetProperty(playerList.get(), it->second.first.c_str(), player); 
     443  } 
     444 
     445  return playerList; 
     446} 
     447 
     448CScriptValRooted XmppClient::GUIGetGameList() 
     449{ 
     450  CScriptValRooted gameList; 
     451  //GetScriptInterface().Eval("({})", gameList); 
     452  GetScriptInterface().Eval("([])", gameList); 
     453  for(std::list<GameItemData>::iterator it = m_GameList.begin(); it !=m_GameList.end(); ++it) 
     454  { 
     455    CScriptValRooted game; 
     456    GetScriptInterface().Eval("({})", game); 
     457 
     458#define ITEM(param)\ 
     459    GetScriptInterface().SetProperty(game.get(), #param, it->m_##param .c_str()); 
     460    ITEMS 
     461#undef ITEM 
     462 
     463    //GetScriptInterface().SetProperty(gameList.get(), it->m_name.c_str(), game); 
     464    GetScriptInterface().CallFunctionVoid(gameList.get(), "push", game); 
     465  } 
     466 
     467  return gameList; 
     468} 
     469 
     470/* Messages */ 
     471CScriptValRooted XmppClient::GuiPollMessage() 
     472{ 
     473  if (m_GuiMessageQueue.empty()) 
     474    return CScriptValRooted(); 
     475 
     476  CScriptValRooted r = m_GuiMessageQueue.front(); 
     477  m_GuiMessageQueue.pop_front(); 
     478  return r; 
     479} 
     480 
     481void XmppClient::SendMUCMessage(std::string message) 
     482{ 
     483  _mucRoom->send(message); 
     484} 
     485 
     486void XmppClient::PushGuiMessage(const CScriptValRooted& message) 
     487{ 
     488  ENSURE(!message.undefined()); 
     489 
     490  m_GuiMessageQueue.push_back(message); 
     491} 
     492 
     493void XmppClient::CreateSimpleMessage(std::string type, std::string text, std::string level) 
     494{ 
     495  CScriptValRooted message; 
     496  GetScriptInterface().Eval("({})", message); 
     497  GetScriptInterface().SetProperty(message.get(), "type", type); 
     498  GetScriptInterface().SetProperty(message.get(), "level", level); 
     499  GetScriptInterface().SetProperty(message.get(), "text", text); 
     500  PushGuiMessage(message); 
     501} 
     502 
     503/* 
     504 *  GameListQuery, custom IQ Stanza 
     505 */ 
     506 
     507GameListQuery::GameListQuery( const Tag* tag ) 
     508: StanzaExtension( ExtGameListQuery ) 
     509{ 
     510  if( !tag || tag->name() != "query" || tag->xmlns() != XMLNS_GAMELIST ) 
     511    return; 
     512 
     513  const Tag* c = tag->findTag( "query/game" ); 
     514  if (c) 
     515    m_command = c->cdata(); 
     516 
     517  const ConstTagList& l = tag->findTagList( "query/game" ); 
     518  ConstTagList::const_iterator it = l.begin(); 
     519  for( ; it != l.end(); ++it ) 
     520  { 
     521    GameItemData *pItem = new GameItemData(); 
     522#define ITEM(param)\ 
     523    const std::string param = (*it)->findAttribute( #param ); \ 
     524    pItem->m_##param = param; 
     525    ITEMS 
     526#undef ITEM 
     527    m_gameList.push_back( pItem ); 
     528  } 
     529} 
     530 
     531GameListQuery::~GameListQuery() 
     532{ 
     533  util::clearList( m_gameList ); 
     534} 
     535 
     536const std::string& GameListQuery::filterString() const 
     537{ 
     538  static const std::string filter = "/iq/query[@xmlns='" + XMLNS_GAMELIST + "']"; 
     539  return filter; 
     540} 
     541 
     542Tag* GameListQuery::tag() const 
     543{ 
     544  Tag* t = new Tag( "query" ); 
     545  t->setXmlns( XMLNS_GAMELIST ); 
     546/* 
     547  RosterData::const_iterator it = m_roster.begin(); 
     548  for( ; it != m_roster.end(); ++it ) 
     549  t->addChild( (*it)->tag() ); 
     550*/ 
     551 
     552  // register / unregister command 
     553  if(!m_command.empty()) 
     554    t->addChild(new Tag("command", m_command)); 
     555 
     556  std::list<GameItemData*>::const_iterator it = m_gameList.begin(); 
     557  for( ; it != m_gameList.end(); ++it ) 
     558    t->addChild( (*it)->tag() ); 
     559 
     560  return t; 
     561} 
     562 
     563StanzaExtension* GameListQuery::clone() const 
     564{ 
     565  GameListQuery* q = new GameListQuery(); 
     566 
     567  return q; 
     568} 
     569 
     570const std::list<GameItemData*>& GameListQuery::gameList() const 
     571{ 
     572  return m_gameList; 
     573} 
  • source/lobby/GameItemData.h

     
     1#ifndef GAMEITEMDATA_H 
     2#define GAMEITEMDATA_H 
     3 
     4#include <string> 
     5 
     6#define ITEMS \ 
     7  ITEM(name)      \ 
     8  ITEM(ip)        \ 
     9  ITEM(nbp)       \ 
     10  ITEM(tnbp)      \ 
     11  ITEM(mapName)   \ 
     12  ITEM(mapSize)   \ 
     13  ITEM(victoryCondition) 
     14 
     15class GameItemData 
     16{ 
     17  friend class XmppClient; 
     18  friend class GameListQuery; 
     19public: 
     20  GameItemData(std::string name= "", std::string ip = "") 
     21  : m_name(name), m_ip(ip) 
     22  { 
     23  } 
     24 
     25  virtual ~GameItemData() {} 
     26 
     27  Tag* tag() const 
     28  { 
     29    Tag* i = new Tag( "game" ); 
     30 
     31#define ITEM(param)\ 
     32    i->addAttribute( #param, m_##param ); 
     33    ITEMS 
     34#undef ITEM 
     35 
     36    return i; 
     37  } 
     38 
     39protected: 
     40#define ITEM(param)\ 
     41  std::string m_##param ; 
     42  ITEMS 
     43#undef ITEM 
     44}; 
     45 
     46#endif 
  • source/lobby/XmppClient.h

     
     1#ifndef XXXMPPCLIENT_H 
     2#define XXXMPPCLIENT_H 
     3 
     4//network 
     5#include <gloox/jid.h> 
     6#include <gloox/client.h> 
     7#include <gloox/mucroom.h> 
     8#include <gloox/message.h> 
     9 
     10#include <gloox/messagehandler.h> 
     11#include <gloox/presencehandler.h> 
     12#include <gloox/mucroomhandler.h> 
     13#include <gloox/loghandler.h> 
     14#include <gloox/connectionlistener.h> 
     15#include <gloox/registration.h> 
     16 
     17#include <gloox/iq.h> 
     18#include <gloox/iqhandler.h> 
     19 
     20//game - script 
     21#include <deque> 
     22#include "scriptinterface/ScriptVal.h" 
     23 
     24//Global Gamelist Extension 
     25#define ExtGameListQuery 1403 
     26const std::string XMLNS_GAMELIST = "jabber:iq:gamelist"; 
     27 
     28//debug 
     29using namespace gloox; 
     30 
     31//Game - script 
     32class ScriptInterface; 
     33class GameItemData; 
     34 
     35class XmppClient : public ConnectionListener, public MUCRoomHandler, public IqHandler, public LogHandler, public RegistrationHandler, public MessageHandler 
     36{ 
     37private: 
     38  //Game - script 
     39  ScriptInterface& m_ScriptInterface; 
     40  //Components 
     41  Client* _client; 
     42  MUCRoom* _mucRoom; 
     43  Registration* _registration; 
     44  //Account infos 
     45  std::string _username; 
     46  std::string _password; 
     47  std::string _nick; 
     48  std::string _xpartamuppId; 
     49 
     50public: 
     51  //Basic 
     52  XmppClient(ScriptInterface& scriptInterface, std::string sUsername, std::string sPassword, std::string sRoom, std::string sNick, bool regOpt = false); 
     53  virtual ~XmppClient(); 
     54 
     55  //Network 
     56  void connect(); 
     57  void disconnect(); 
     58  void recv(); 
     59  void SendIqGetGameList(); 
     60  void SendIqRegisterGame(CScriptVal data); 
     61  void SendIqUnregisterGame(std::string name); 
     62 
     63  CScriptValRooted GUIGetPlayerList(); 
     64  CScriptValRooted GUIGetGameList(); 
     65 
     66  //Script 
     67  ScriptInterface& GetScriptInterface(); 
     68 
     69protected: 
     70  /* Xmpp handlers */ 
     71  /* MUC handlers */ 
     72  virtual void handleMUCParticipantPresence(gloox::MUCRoom*, gloox::MUCRoomParticipant, const gloox::Presence&); 
     73  virtual bool handleMUCRoomCreation(gloox::MUCRoom*) {return false;} 
     74  virtual void handleMUCSubject(gloox::MUCRoom*, const std::string&, const std::string&) {} 
     75  virtual void handleMUCInviteDecline(gloox::MUCRoom*, const gloox::JID&, const std::string&) {} 
     76  virtual void handleMUCError(gloox::MUCRoom*, gloox::StanzaError); 
     77  virtual void handleMUCInfo(gloox::MUCRoom*, int, const std::string&, const gloox::DataForm*) {} 
     78  virtual void handleMUCItems(gloox::MUCRoom*, const std::list<gloox::Disco::Item*, std::allocator<gloox::Disco::Item*> >&); 
     79  virtual void handleMUCMessage( MUCRoom* room, const Message& msg, bool priv ); 
     80 
     81  /* Log handler */ 
     82  virtual void handleLog( LogLevel level, LogArea area, const std::string& message ); 
     83 
     84  /* ConnectionListener handlers*/ 
     85  virtual void onConnect(); 
     86  virtual void onDisconnect( ConnectionError e ); 
     87  virtual bool onTLSConnect( const CertInfo& info ); 
     88 
     89  /* Iq Handlers */ 
     90  virtual bool handleIq( const IQ& iq ); 
     91  virtual void handleIqID( const IQ&, int ) {} 
     92 
     93  /* Registration Handlers */ 
     94  virtual void handleRegistrationFields( const JID& /*from*/, int fields, std::string instructions ); 
     95  virtual void handleRegistrationResult( const JID& /*from*/, RegistrationResult result ); 
     96  virtual void handleAlreadyRegistered( const JID& /*from*/ ); 
     97  virtual void handleDataForm( const JID& /*from*/, const DataForm& /*form*/ ); 
     98  virtual void handleOOB( const JID& /*from*/, const OOB& oob ); 
     99 
     100  /* Message Handler */ 
     101  virtual void handleMessage( const Message& msg, MessageSession * session ); 
     102 
     103  /* Messages */ 
     104public: 
     105  CScriptValRooted GuiPollMessage(); 
     106  void SendMUCMessage(std::string message); 
     107protected: 
     108  void PushGuiMessage(const CScriptValRooted& message); 
     109  void CreateSimpleMessage(std::string type, std::string text, std::string level = "standard"); 
     110 
     111private: 
     112  /// Map of players 
     113  std::map<std::string, std::pair<std::string, int> > m_PlayerMap; 
     114  /// List of games 
     115  std::list< GameItemData > m_GameList; 
     116  /// Queue of messages 
     117  std::deque<CScriptValRooted> m_GuiMessageQueue; 
     118}; 
     119 
     120class GameListQuery : public StanzaExtension 
     121{ 
     122  friend class XmppClient; 
     123public: 
     124  GameListQuery( const Tag* tag = 0 ); 
     125 
     126  ~GameListQuery(); 
     127 
     128  // reimplemented from StanzaExtension 
     129  virtual const std::string& filterString() const; 
     130 
     131  // reimplemented from StanzaExtension 
     132  virtual StanzaExtension* newInstance( const Tag* tag ) const 
     133  { 
     134    return new GameListQuery( tag ); 
     135  } 
     136 
     137  // reimplemented from StanzaExtension 
     138  virtual Tag* tag() const; 
     139 
     140  // reimplemented from StanzaExtension 
     141  virtual StanzaExtension* clone() const; 
     142 
     143  const std::list<GameItemData*>& gameList() const; 
     144 
     145private: 
     146  std::string m_command; 
     147  std::list<GameItemData*> m_gameList; 
     148}; 
     149 
     150extern XmppClient *g_XmppClient; 
     151 
     152#endif // XMPPCLIENT_H 
  • source/pch/lobby/precompiled.cpp

     
     1/* Copyright (C) 2009 Wildfire Games. 
     2 * This file is part of 0 A.D. 
     3 * 
     4 * 0 A.D. is free software: you can redistribute it and/or modify 
     5 * it under the terms of the GNU General Public License as published by 
     6 * the Free Software Foundation, either version 2 of the License, or 
     7 * (at your option) any later version. 
     8 * 
     9 * 0 A.D. is distributed in the hope that it will be useful, 
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12 * GNU General Public License for more details. 
     13 * 
     14 * You should have received a copy of the GNU General Public License 
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>. 
     16 */ 
     17 
     18#include "precompiled.h" 
  • source/pch/lobby/precompiled.h

     
     1/* Copyright (C) 2009 Wildfire Games. 
     2 * This file is part of 0 A.D. 
     3 * 
     4 * 0 A.D. is free software: you can redistribute it and/or modify 
     5 * it under the terms of the GNU General Public License as published by 
     6 * the Free Software Foundation, either version 2 of the License, or 
     7 * (at your option) any later version. 
     8 * 
     9 * 0 A.D. is distributed in the hope that it will be useful, 
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12 * GNU General Public License for more details. 
     13 * 
     14 * You should have received a copy of the GNU General Public License 
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>. 
     16 */ 
     17 
     18#include "lib/precompiled.h"    // common precompiled header 
  • binaries/data/mods/public/gui/pregame/mainmenu.xml

     
    196196                    Matches 
    197197                    <action on="Press"> 
    198198                        closeMenu(); 
    199                         Engine.PushGuiPage("page_gamesetup.xml", { type: "offline" }); 
     199                        Engine.PushGuiPage("page_gamesetup.xml", { type: "offline", source: "mainmenu" }); 
    200200                    </action> 
    201201                </object> 
    202202 
     
    253253                    <action on="Press"> 
    254254                        closeMenu(); 
    255255                        // Open Multiplayer connection window with join option. 
    256                         Engine.PushGuiPage("page_gamesetup_mp.xml", "join"); 
     256                        Engine.PushGuiPage("page_gamesetup_mp.xml", { multiplayerGameType: "join", source: "mainmenu" }); 
    257257                    </action> 
    258258                </object> 
    259259 
     
    268268                    <action on="Press"> 
    269269                        closeMenu(); 
    270270                        // Open Multiplayer connection window with host option. 
    271                         Engine.PushGuiPage("page_gamesetup_mp.xml", "host"); 
     271                        Engine.PushGuiPage("page_gamesetup_mp.xml", { multiplayerGameType: "host", source: "mainmenu" }); 
    272272                    </action> 
    273273                </object> 
    274             </object> 
    275274 
     275                <object name="subMenuMultiplayerLobbyButton" 
     276                    type="button" 
     277                    style="StoneButtonFancy" 
     278                    size="0 64 100% 92" 
     279                    tooltip_style="pgToolTip" 
     280                    tooltip="Launch the multiplayer lobby." 
     281                > 
     282                    Game Lobby 
     283                    <action on="Press"> 
     284                        closeMenu(); 
     285                        // Open Multiplayer game lobby. 
     286                        Engine.PushGuiPage("page_prelobby.xml", []); 
     287                    </action> 
     288                </object> 
     289                </object> 
     290 
    276291            <!-- submenuToolsAndOptions --> 
    277292            <object name="submenuToolsAndOptions" 
    278293                type="image" 
     
    402417                    Multiplayer 
    403418                    <action on="Press"> 
    404419                        closeMenu(); 
    405                         openMenu("submenuMultiplayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 2); 
     420                        openMenu("submenuMultiplayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 3); 
    406421                    </action> 
    407422                </object> 
    408423 
  • binaries/data/mods/public/gui/gamesetup/gamesetup_mp.js

     
    11var g_IsConnecting = false; 
    22var g_GameType; // "server" or "client" 
     3var g_Source; // "mainmenu" or "lobby" 
     4var g_ServerName = ""; 
     5var g_Name; 
     6var g_Ip; 
    37 
    48var g_IsRejoining = false; 
    59var g_GameAttributes; // used when rejoining 
    610var g_PlayerAssignments; // used when rejoining 
    711 
    8 function init(multiplayerGameType) 
     12function init(attribs) 
    913{ 
    10     switch (multiplayerGameType) 
     14        switch (attribs.multiplayerGameType) 
     15        { 
     16                case "join": 
     17                        getGUIObjectByName("pageJoin").hidden = false; 
     18                        getGUIObjectByName("pageHost").hidden = true; 
     19                        break; 
     20                case "host": 
     21                        getGUIObjectByName("pageJoin").hidden = true; 
     22                        getGUIObjectByName("pageHost").hidden = false; 
     23                        break; 
     24                default: 
     25                        error("Unrecognised multiplayer game type : " + attribs.multiplayerGameType); 
     26                        break; 
     27        } 
     28     
     29    switch (attribs.source) 
    1130    { 
    12     case "join": 
    13         getGUIObjectByName("pageJoin").hidden = false; 
    14         getGUIObjectByName("pageHost").hidden = true; 
    15         break; 
    16     case "host": 
    17         getGUIObjectByName("pageJoin").hidden = true; 
    18         getGUIObjectByName("pageHost").hidden = false; 
    19         break; 
    20     default: 
    21         error("Unrecognised multiplayer game type : " + multiplayerGameType); 
    22         break; 
     31        case "mainmenu": 
     32            g_Source = "mainmenu"; 
     33            break; 
     34        case "lobby": 
     35            g_Source = "lobby"; 
     36            getGUIObjectByName("hostServerNameWrapper").hidden = false; 
     37            break; 
     38        default: 
     39            error("Unrecognised source : " + attribs.source); 
    2340    } 
     41 
     42    if (attribs.name) 
     43    { 
     44        getGUIObjectByName("hostPlayerName").caption = attribs.name; 
     45        getGUIObjectByName("joinPlayerName").caption = attribs.name; 
     46    } 
     47    if (attribs.ip) getGUIObjectByName("joinIP").caption = attribs.ip; 
    2448} 
    2549 
    2650function cancelSetup() 
    2751{ 
    2852    if (g_IsConnecting) 
    2953        Engine.DisconnectNetworkGame(); 
    30     Engine.PopGuiPage();     
     54    Engine.PopGuiPage(); 
    3155} 
    3256 
    3357function startConnectionStatus(type) 
     
    4367    if (!g_IsConnecting) 
    4468        return; 
    4569 
     70    pollAndHandleNetworkClient(); 
     71} 
     72 
     73function pollAndHandleNetworkClient() 
     74{ 
    4675    while (true) 
    4776    { 
    4877        var message = Engine.PollNetworkClient(); 
     
    119148                    else 
    120149                    { 
    121150                        Engine.PopGuiPage(); 
    122                         Engine.PushGuiPage("page_gamesetup.xml", { "type": g_GameType }); 
     151                        Engine.PushGuiPage("page_gamesetup.xml", { "type": g_GameType, "source": g_Source, "serverName": g_ServerName }); 
    123152                        return; // don't process any more messages - leave them for the game GUI loop 
    124153                    } 
    125154 
     
    163192    } 
    164193 
    165194    startConnectionStatus("server"); 
    166     // TODO: ought to do something(?) with servername 
     195    g_ServerName = servername; 
    167196 
    168197    return true; 
    169198} 
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

     
    1919// Is this user in control of game settings (i.e. is a network server, or offline player) 
    2020var g_IsController; 
    2121 
     22// Where this user come from ("mainmenu" or "lobby") 
     23var g_Source; 
     24 
     25//Server name, if user is a server, connected to the multiplayer lobby 
     26var g_ServerName; 
     27 
    2228// Are we currently updating the GUI in response to network messages instead of user input 
    2329// (and therefore shouldn't send further messages to the network) 
    2430var g_IsInGuiUpdate; 
     
    6975    default: 
    7076        error("Unexpected 'type' in gamesetup init: "+attribs.type); 
    7177    } 
     78 
     79    switch (attribs.source) 
     80    { 
     81    case "mainmenu": 
     82        g_Source = "mainmenu"; 
     83        break; 
     84    case "lobby": 
     85        g_Source = "lobby"; 
     86        break; 
     87    default: 
     88        error("Unrecognised source : " + attribs.source); 
     89    } 
     90 
     91        if (attribs.serverName) 
     92        g_ServerName = attribs.serverName; 
    7293} 
    7394 
    7495// Called after the map data is loaded and cached 
     
    156177                updateGameAttributes(); 
    157178            } 
    158179        }; 
     180        mapSize.selected = 0; 
    159181 
    160182        getGUIObjectByName("revealMap").onPress = function() 
    161183        {   // Update attributes so other players can see change 
     
    281303        { 
    282304        case "disconnected": 
    283305            Engine.DisconnectNetworkGame(); 
     306            if (isServerOnLobby()) Engine.SendUnregisterGame(g_ServerName); 
    284307            Engine.PopGuiPage(); 
    285308            reportDisconnect(message.reason); 
    286309            break; 
     
    319342        // Update the player list 
    320343        g_PlayerAssignments = message.hosts; 
    321344        updatePlayerList(); 
     345 
     346        if (isServerOnLobby()) 
     347        { 
     348            sendRegisterGameStanza(); 
     349        } 
    322350        break; 
    323351 
    324352    case "start": 
     353        if (g_Source == "lobby") Engine.StopXmppClient(); 
    325354        Engine.SwitchGuiPage("page_loading.xml", { 
    326355            "attribs": g_GameAttributes, 
    327356            "isNetworked" : g_IsNetworked, 
     
    942971    if (g_IsNetworked) 
    943972    { 
    944973        Engine.SetNetworkGameAttributes(g_GameAttributes); 
     974        if (isServerOnLobby() && g_LoadingState >= 2) 
     975        { 
     976            sendRegisterGameStanza(); 
     977        } 
    945978    } 
    946979    else 
    947980    { 
     
    12591292    } 
    12601293    return false; 
    12611294} 
     1295 
     1296function isServerOnLobby() 
     1297{ 
     1298    return (g_IsController && g_Source == "lobby") ? true : false; 
     1299} 
     1300 
     1301function sendRegisterGameStanza() 
     1302{ 
     1303    var selectedMapSize = getGUIObjectByName("mapSize").selected; 
     1304    var selectedVictoryCondition = getGUIObjectByName("victoryCondition").selected; 
     1305 
     1306    var mapSize = getGUIObjectByName("mapSize").list_data[selectedMapSize]; 
     1307    var victoryCondition = getGUIObjectByName("victoryCondition").list[selectedVictoryCondition]; 
     1308 
     1309    var numberOfPlayers = 0; 
     1310    for (var guid in g_PlayerAssignments) 
     1311    {    
     1312        numberOfPlayers++; 
     1313    } 
     1314        print(numberOfPlayers); 
     1315 
     1316    var nbp = numberOfPlayers ? numberOfPlayers : 1; 
     1317    var tnbp = g_GameAttributes.settings.PlayerData.length; 
     1318 
     1319    gameData = { 
     1320        "name":g_ServerName, 
     1321        "mapName":g_GameAttributes.map, 
     1322        "mapSize":mapSize, 
     1323        "victoryCondition":victoryCondition,  
     1324        "nbp":nbp, 
     1325        "tnbp":tnbp 
     1326    }; 
     1327    Engine.SendRegisterGame(gameData); 
     1328} 
  • binaries/data/mods/public/gui/gamesetup/gamesetup_mp.xml

     
    7272                ]]></action> 
    7373            </object> 
    7474 
    75             <object hidden="true"> <!-- TODO: restore this when the server name is actually used --> 
     75            <object name="hostServerNameWrapper" hidden="true"> 
    7676            <object type="text" size="0 80 200 110" style="RightLabelText"> 
    7777                Server name: 
    7878            </object> 
  • binaries/data/mods/public/gui/gamesetup/gamesetup.xml

     
    240240            style="StoneButton" 
    241241            size="100%-164 100%-52 100%-24 100%-24" 
    242242            tooltip_style="onscreenToolTip" 
    243             tooltip="Return to the main menu." 
    244243        > 
    245             Main menu 
     244            <action on="Load"><![CDATA[ 
     245              if(!isServerOnLobby()) 
     246              { 
     247                this.caption = "Main menu"; 
     248                this.tooltip = "Return to the main menu." 
     249              } 
     250              else 
     251              { 
     252                this.caption = "Quit"; 
     253                this.tooltip = "Return to the lobby." 
     254              } 
     255            ]]></action> 
    246256            <action on="Press"> 
    247257                <![CDATA[ 
    248258                    cancelSetup(); 
     259                    if(isServerOnLobby()) Engine.SendUnregisterGame(g_ServerName); 
    249260                    Engine.PopGuiPage(); 
    250261                ]]> 
    251262            </action> 
  • binaries/data/mods/public/gui/page_lobby.xml

     
     1<?xml version="1.0" encoding="utf-8"?> 
     2<page> 
     3  <include>common/setup.xml</include> 
     4  <include>common/styles.xml</include> 
     5  <include>common/sprite1.xml</include> 
     6 
     7<include>common/common_sprites.xml</include> 
     8<include>common/common_styles.xml</include> 
     9 
     10  <include>lobby/styles.xml</include> 
     11  <include>lobby/lobby.xml</include> 
     12</page> 
  • binaries/data/mods/public/gui/page_prelobby.xml

     
     1<?xml version="1.0" encoding="utf-8"?> 
     2<page> 
     3  <include>common/setup.xml</include> 
     4  <include>common/styles.xml</include> 
     5  <include>common/sprite1.xml</include> 
     6 
     7<include>common/common_sprites.xml</include> 
     8<include>common/common_styles.xml</include> 
     9 
     10  <include>gamesetup/styles.xml</include> 
     11  <include>summary/sprites.xml</include> 
     12  <include>lobby/prelobby.xml</include> 
     13</page> 
     14 
  • binaries/data/config/default.cfg

     
    241241joystick.camera.rotate.y = 2 
    242242joystick.camera.zoom.in = 5 
    243243joystick.camera.zoom.out = 4 
     244 
     245; Multiplayer lobby preferences 
     246lobby.server = "localhost" 
     247lobby.xpartamupp = "xpartamupp"