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

File 0ad-multiplayer-lobby-v30-06-2012bis.diff, 69.0 KB (added by Badmadblacksad-, 12 years ago)

This patch should fixes the namespace issues. It also includes Ben's changes to extern_libs.lua & premake4.lua and the missing precompiled.h header in XmppClient.cpp.

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