Ticket #2447: readyv3.patch

File readyv3.patch, 26.3 KB (added by scythetwirler, 10 years ago)
  • binaries/data/mods/public/gui/common/modern/sprites.xml

     
    296296            size="0 0 22 22"
    297297        />
    298298    </sprite>
     299    <sprite name="ModernCheckOn">
     300        <image  texture="global/modern/checkbox-on.png"
     301            real_texture_placement="0 0 32 32"
     302        />
     303    </sprite>
     304    <sprite name="ModernCheckOff">
     305        <image  texture="global/modern/checkbox-off.png"
     306            real_texture_placement="0 0 32 32"
     307        />
     308    </sprite>
    299309</sprites>
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

     
    3131// (and therefore shouldn't send further messages to the network)
    3232var g_IsInGuiUpdate;
    3333
     34// Is this user ready
     35var g_IsReady;
     36
    3437var g_PlayerAssignments = {};
    3538
    3639// Default game setup attributes
     
    97100    {
    98101        cancelButton.tooltip = "Return to the lobby."
    99102    }
    100 
     103    if (!g_IsNetworked)     
     104        Engine.GetGUIObjectByName("toggleReady").hidden = true;
    101105}
    102106
    103107// Called after the map data is loaded and cached
     
    412416        break;
    413417
    414418    case "players":
     419        var playersChanged = false;
    415420        // Find and report all joinings/leavings
    416421        for (var host in message.hosts)
    417422            if (! g_PlayerAssignments[host])
     423            {
    418424                addChatMessage({ "type": "connect", "username": message.hosts[host].name });
     425                playersChanged = true;
     426            }
    419427
    420428        for (var host in g_PlayerAssignments)
    421429            if (! message.hosts[host])
     430            {
    422431                addChatMessage({ "type": "disconnect", "guid": host });
     432                playersChanged = true;
     433            }
    423434
    424435        // Update the player list
    425436        g_PlayerAssignments = message.hosts;
     437        if (playersChanged)
     438            resetReadyData();
     439        updateReadyUI();
    426440        updatePlayerList();
    427 
    428441        if (g_IsController)
    429442            sendRegisterGameStanza();
    430443        break;
     
    447460        addChatMessage({ "type": "message", "guid": message.guid, "text": message.text });
    448461        break;
    449462
     463    // Singular client to host message
     464    case "ready":       
     465        if (!g_IsController)
     466            break;
     467        g_PlayerAssignments[message.guid].status = (parseInt(message.text) == 1);
     468        Engine.AssignNetworkPlayerStatus(parseInt(message.text), message.guid);
     469        updateReadyUI();
     470        break;
     471
    450472    default:
    451473        error("Unrecognised net message type "+message.type);
    452474    }
     
    705727            if (g_IsNetworked)
    706728                Engine.AssignNetworkPlayer(player, "");
    707729            else
    708                 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1} };
     730                g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1, "ready": 0} };
    709731        }
    710732    }
    711733
     
    822844    // Reset player assignments on map change
    823845    if (!g_IsNetworked)
    824846    {   // Slot 1
    825         g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1} };
     847        g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1, "ready": 0} };
    826848    }
    827849    else
    828850    {
     
    842864
    843865function launchGame()
    844866{
     867    if (g_IsNetworked && !g_IsReady)
     868    {
     869        for (var guid in g_PlayerAssignments)
     870        {
     871            if (g_PlayerAssignments[guid].name.split(" (")[0] == Engine.ConfigDB_GetValue("user", "playername") && g_PlayerAssignments[guid].player == -1)
     872                break; // Observers don't need to be ready.
     873            else
     874                return; // Host may have changed their own code.
     875        }
     876    }
    845877    if (g_IsNetworked && !g_IsController)
    846878    {
    847879        error("Only host can start game");
     
    11841216        if (i >= numPlayers)
    11851217            continue;
    11861218
    1187         var pName = Engine.GetGUIObjectByName("playerName["+i+"]");
    11881219        var pCiv = Engine.GetGUIObjectByName("playerCiv["+i+"]");
    11891220        var pCivText = Engine.GetGUIObjectByName("playerCivText["+i+"]");
    11901221        var pTeam = Engine.GetGUIObjectByName("playerTeam["+i+"]");
     
    11981229        // Common to all game types
    11991230        var color = iColorToString(getSetting(pData, pDefs, "Colour"));
    12001231        pColor.sprite = "colour:"+color+" 100";
    1201         pName.caption = getSetting(pData, pDefs, "Name");
    12021232
    12031233        var team = getSetting(pData, pDefs, "Team");
    12041234        var civ = getSetting(pData, pDefs, "Civ");
     
    12351265
    12361266    // Game attributes include AI settings, so update the player list
    12371267    updatePlayerList();
     1268
     1269    // We should have everyone confirm that the new settings are acceptable.
     1270    resetReadyData();
    12381271}
    12391272
    12401273function updateGameAttributes()
     
    14041437                        swapPlayers(guid, playerSlot);
    14051438
    14061439                    Engine.SetNetworkGameAttributes(g_GameAttributes);
     1440                    updateReadyUI();
    14071441                }
    14081442            };
    14091443        }
     
    15341568    Engine.GetGUIObjectByName("moreOptions").hidden = !Engine.GetGUIObjectByName("moreOptions").hidden;
    15351569}
    15361570
     1571function toggleReady()
     1572{
     1573    g_IsReady = !g_IsReady;
     1574    if (g_IsReady)
     1575        Engine.SendNetworkReady(1);
     1576    else
     1577        Engine.SendNetworkReady(0);
     1578}
     1579
     1580function updateReadyUI()
     1581{
     1582    var allReady = true;
     1583    for (var guid in g_PlayerAssignments)
     1584    {
     1585        // We don't really care whether observers are ready.
     1586        if (g_PlayerAssignments[guid].player == -1)
     1587            return;
     1588        if (g_PlayerAssignments[guid].status || !g_IsNetworked)
     1589            Engine.GetGUIObjectByName("playerReadySprite[" + String(g_PlayerAssignments[guid].player - 1) + "]").sprite = "ModernCheckOn";
     1590        else
     1591        {
     1592            Engine.GetGUIObjectByName("playerReadySprite[" + String(g_PlayerAssignments[guid].player - 1) + "]").sprite = "ModernCheckOff";
     1593            allReady = false;
     1594        }
     1595    }
     1596    // AIs are always ready.
     1597    for (var playerid = 0; playerid < MAX_PLAYERS; playerid++)
     1598    {
     1599        if (g_GameAttributes.settings.PlayerData[playerid])
     1600        {
     1601            if (g_GameAttributes.settings.PlayerData[playerid].AI != "" || g_GameAttributes.settings.PlayerData[playerid].Name == "Unassigned")
     1602                Engine.GetGUIObjectByName("playerReadySprite[" + String(playerid) + "]").sprite = "ModernCheckOn";
     1603        }
     1604    }
     1605
     1606    // The host is not allowed to start until everyone is ready.
     1607    if (g_IsNetworked && g_IsController)
     1608        Engine.GetGUIObjectByName("startGame").enabled = allReady;
     1609}
     1610
     1611function resetReadyData()
     1612{
     1613    g_IsReady = false;
     1614    if (g_IsNetworked && g_IsController)
     1615        Engine.ClearAllPlayerReady();
     1616}
    15371617////////////////////////////////////////////////////////////////////////////////////////////////
    15381618// Basic map filters API
    15391619
  • binaries/data/mods/public/gui/gamesetup/gamesetup.xml

     
    1414        <object style="TitleText" type="text" size="50%-128 4 50%+128 36">
    1515            Match Setup
    1616        </object>
    17    
     17
    1818        <object type="image" style="ModernDialog" size="50%-190 50%-80 50%+190 50%+80" name="loadingWindow">
    1919
    2020            <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16">
     
    3232            <action on="Tick">
    3333                onTick();
    3434            </action>
    35            
     35
    3636            <!-- Number of Players-->
    3737            <object size="24 26 224 54">
    3838
     
    4040                <object size="0 0 150 28">
    4141                    <object size="0 0 100% 100%" type="text" style="ModernRightLabelText">Number of players:</object>
    4242                </object>
    43                    
     43
    4444                <!-- Number of Players-->
    4545                <object size="150 0 200 28">
    4646                    <object name="numPlayersText" size="0 0 100% 100%" type="text" style="ModernLeftLabelText"/>
     
    5353                        <action on="SelectionChange">selectNumPlayers(this.list_data[this.selected]);</action>
    5454                    </object>
    5555                </object>
     56            </object>
    5657
    57             </object>
    58            
    5958            <!-- Player assignments -->
    6059            <object size="24 59 100%-440 358" type="image" sprite="ModernDarkBoxGold" name="playerAssignmentsPannel">
    6160                <object size="0 6 100% 30">
    62                     <object name="playerNameHeading" type="text" style="ModernLabelText" size="0 0 20% 100%">Player Name</object>
    63                     <object name="playerPlacementHeading" type="text" style="ModernLabelText" size="20%+5 0 50% 100%">Player Placement</object>
    64                     <object name="playerCivHeading" type="text" style="ModernLabelText" size="50%+65 0 85% 100%">Civilization</object>
     61                    <object name="playerPlacementHeading" type="text" style="ModernLabelText" size="5 0 40% 100%">Player Name</object>
     62                    <object name="playerCivHeading" type="text" style="ModernLabelText" size="40%+65 0 75%-26 100%">Civilization</object>
    6563                    <object name="civInfoButton"
    6664                        type="button"
    6765                        sprite="iconInfoGold"
    6866                        sprite_over="iconInfoWhite"
    69                         size="82%-8 0 82%+8 16"
     67                        size="57.5%+68 0 57.5%+84 16"
    7068                        tooltip_style="onscreenToolTip"
    7169                        tooltip="View civilization info"
    7270                    >
     
    7472                            Engine.PushGuiPage("page_civinfo.xml");
    7573                        ]]></action>
    7674                    </object>
    77                     <object name="playerTeamHeading" type="text" style="ModernLabelText" size="85%+5 0 100%-5 100%">Team</object>
     75                    <object name="playerTeamHeading" type="text" style="ModernLabelText" size="75%+5 0 90%-5 100%">Team</object>
     76                    <object name="playerReadyHeading" type="text" style="ModernLabelText" size="90%+5 0 100%-5 100%">Ready</object>
    7877                </object>
    7978                <object size="1 36 100%-1 100%">
    8079                    <repeat count="8">
    8180                        <object name="playerBox[n]" size="0 0 100% 32" hidden="true">
    8281                            <object name="playerColour[n]" type="image" size="0 0 100% 100%"/>
    83                             <object name="playerName[n]" type="text" style="ModernLabelText" size="0 2 20% 30"/>
    84                             <object name="playerAssignment[n]" type="dropdown" style="ModernDropDown" size="20%+5 2 50% 30" tooltip_style="onscreenToolTip" tooltip="Select player."/>
    85                             <object name="playerConfig[n]" type="button" style="StoneButton" size="50%+5 6 50%+60 26"
     82                            <object name="playerAssignment[n]" type="dropdown" style="ModernDropDown" size="5 2 40% 30" tooltip_style="onscreenToolTip" tooltip="Select player."/>
     83                            <object name="playerConfig[n]" type="button" style="StoneButton" size="40%+5 6 40%+60 26"
    8684                                tooltip_style="onscreenToolTip"
    8785                                tooltip="Configure AI settings."
    8886                                font="serif-bold-stroke-12"
    8987                            >Settings</object>
    90                             <object name="playerCiv[n]" type="dropdown" style="ModernDropDown" size="50%+65 2 85% 30" tooltip_style="onscreenToolTip" tooltip="Select player's civilization."/>
    91                             <object name="playerCivText[n]" type="text" style="ModernLabelText" size="50%+65 0 85% 30"/>
    92                             <object name="playerTeam[n]" type="dropdown" style="ModernDropDown" size="85%+5 2 100%-5 30" tooltip_style="onscreenToolTip" tooltip="Select player's team."/>
    93                             <object name="playerTeamText[n]" type="text" style="ModernLabelText" size="85%+5 0 100%-5 100%"/>
     88                            <object name="playerCiv[n]" type="dropdown" style="ModernDropDown" size="40%+65 2 75% 30" tooltip_style="onscreenToolTip" tooltip="Select player's civilization."/>
     89                            <object name="playerCivText[n]" type="text" style="ModernLabelText" size="40%+65 0 75% 30"/>
     90                            <object name="playerTeam[n]" type="dropdown" style="ModernDropDown" size="75%+5 2 90%-5 30" tooltip_style="onscreenToolTip" tooltip="Select player's team."/>
     91                            <object name="playerTeamText[n]" type="text" style="ModernLabelText" size="75%+5 0 90%-5 100%"/>
     92                            <object name="playerReadySprite[n]" type="image" sprite="ModernCheckOff" size="95%-16 0 95%+16 32"/>
    9493                        </object>
    9594                    </repeat>
    9695                </object>
    9796            </object>
    98             <object size="24 64 100%-460 358" type="image" sprite="CoverFillDark" name="playerAssignmentsPannelCover" hidden="true"/>
     97            <object size="24 64 100%-460 358" type="image" sprite="CoverFillDark" name="playerAssignmentsPanelCover" hidden="true"/>
    9998            <!-- Map selection -->
    10099           
    101100           
     
    112111                <object name="mapSelectionText" type="text" style="ModernLeftLabelText" size="0 64 100% 94"  hidden="true"/>
    113112                <object name="mapSizeText" type="text" style="ModernLeftLabelText" size="0 96 100% 126" hidden="true"/>
    114113            </object>
    115            
     114
    116115            <object name="mapTypeSelection"
    117116                type="dropdown"
    118117                style="ModernDropDown"
     
    159158            </object>
    160159
    161160            <!-- Chat window -->
    162             <object name="chatPanel" size="24 370 100%-440 100%-60" type="image" sprite="ModernDarkBoxGold">
     161            <object name="chatPanel" size="24 370 100%-440 100%-58" type="image" sprite="ModernDarkBoxGold">
    163162                <object name="chatText" size="2 2 100%-2 100%-26" type="text" style="ChatPanel"/>
    164163
    165164                <object name="chatInput" size="4 100%-24 100%-76 100%-4" type="input" style="ModernInput">
     
    179178                textcolor="white"
    180179                sprite="BackgroundTranslucent"
    181180                hidden="true"
    182                 size="100%-700 100%-56 100%-312 100%-24"
     181                size="25 100%-56 100%-445 100%-24"
    183182            >[Tooltip text]</object>
    184183
     184            <!-- Ready Button -->
     185            <object
     186                name="toggleReady"
     187                type="button"
     188                style="StoneButton"
     189                hidden="false"
     190                size="100%-425 100%-52 100%-305 100%-24"
     191                tooltip_style="onscreenToolTip"
     192                tooltip="Accept the current settings and state you are ready to play!"
     193                enabled="true"
     194            >
     195                Set/Unset Ready
     196                <action on="Press">toggleReady();</action>
     197            </object>
     198
    185199            <!-- Start Button -->
    186200            <object
    187201                name="startGame"
    188202                type="button"
    189203                style="StoneButton"
    190                 size="100%-308 100%-52 100%-168 100%-24"
     204                size="100%-285 100%-52 100%-165 100%-24"
    191205                tooltip_style="onscreenToolTip"
    192206                tooltip="Start a new game with the current settings."
    193207                enabled="false"
     
    202216                caption="Back"
    203217                type="button"
    204218                style="StoneButton"
    205                 size="100%-164 100%-52 100%-24 100%-24"
     219                size="100%-145 100%-52 100%-25 100%-24"
    206220                tooltip_style="onscreenToolTip"
    207221            >
    208222                <action on="Press">
     
    215229                    ]]>
    216230                </action>
    217231            </object>
    218            
     232
    219233            <!-- Options -->
    220234            <object name="gameOptionsBox" size="100%-425 497 100%-25 525">
    221235                <!-- More Options Button -->
  • source/gui/scripting/ScriptFunctions.cpp

     
    343343    g_NetServer->AssignPlayer(playerID, guid);
    344344}
    345345
     346void AssignNetworkPlayerStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int ready, std::string guid)
     347{
     348    ENSURE(g_NetServer);
     349
     350    g_NetServer->ReadyPlayer(ready, guid);
     351}
     352
     353void ClearAllPlayerReady (ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
     354{
     355    ENSURE(g_NetServer);
     356
     357    g_NetServer->ClearAllPlayerReady();
     358}
     359
    346360void SendNetworkChat(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring message)
    347361{
    348362    ENSURE(g_NetClient);
     
    350364    g_NetClient->SendChatMessage(message);
    351365}
    352366
     367void SendNetworkReady(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int message)
     368{
     369    ENSURE(g_NetClient);
     370
     371    g_NetClient->SendReadyMessage(message);
     372}
     373
    353374std::vector<CScriptValRooted> GetAIs(ScriptInterface::CxPrivate* pCxPrivate)
    354375{
    355376    return ICmpAIManager::GetAIs(*(pCxPrivate->pScriptInterface));
     
    838859    scriptInterface.RegisterFunction<CScriptVal, &PollNetworkClient>("PollNetworkClient");
    839860    scriptInterface.RegisterFunction<void, CScriptVal, &SetNetworkGameAttributes>("SetNetworkGameAttributes");
    840861    scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer");
     862    scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayerStatus>("AssignNetworkPlayerStatus");
     863    scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady");
    841864    scriptInterface.RegisterFunction<void, std::wstring, &SendNetworkChat>("SendNetworkChat");
     865    scriptInterface.RegisterFunction<void, int, &SendNetworkReady>("SendNetworkReady");
    842866    scriptInterface.RegisterFunction<std::vector<CScriptValRooted>, &GetAIs>("GetAIs");
    843867    scriptInterface.RegisterFunction<CScriptValRooted, &GetEngineInfo>("GetEngineInfo");
    844868
  • source/network/NetClient.cpp

     
    8787    AddTransition(NCS_INITIAL_GAMESETUP, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context);
    8888
    8989    AddTransition(NCS_PREGAME, (uint)NMT_CHAT, NCS_PREGAME, (void*)&OnChat, context);
     90    AddTransition(NCS_PREGAME, (uint)NMT_READY, NCS_PREGAME, (void*)&OnReady, context);
    9091    AddTransition(NCS_PREGAME, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context);
    9192    AddTransition(NCS_PREGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_PREGAME, (void*)&OnPlayerAssignment, context);
    9293    AddTransition(NCS_PREGAME, (uint)NMT_GAME_START, NCS_LOADING, (void*)&OnGameStart, context);
     
    214215        GetScriptInterface().Eval("({})", host);
    215216        GetScriptInterface().SetProperty(host.get(), "name", std::wstring(it->second.m_Name), false);
    216217        GetScriptInterface().SetProperty(host.get(), "player", it->second.m_PlayerID, false);
     218        GetScriptInterface().SetProperty(host.get(), "status", it->second.m_Status, false);
    217219        GetScriptInterface().SetProperty(hosts.get(), it->first.c_str(), host, false);
    218220    }
    219221
     
    254256    SendMessage(&chat);
    255257}
    256258
     259void CNetClient::SendReadyMessage(const int status)
     260{
     261    CReadyMessage readyStatus;
     262    readyStatus.m_Status = status;
     263    SendMessage(&readyStatus);
     264}
     265
    257266bool CNetClient::HandleMessage(CNetMessage* message)
    258267{
    259268    // Handle non-FSM messages first
     
    419428    return true;
    420429}
    421430
     431bool CNetClient::OnReady(void* context, CFsmEvent* event)
     432{
     433    ENSURE(event->GetType() == (uint)NMT_READY);
     434
     435    CNetClient* client = (CNetClient*)context;
     436
     437    CReadyMessage* message = (CReadyMessage*)event->GetParamRef();
     438
     439    CScriptValRooted msg;
     440    client->GetScriptInterface().Eval("({'type':'ready'})", msg);
     441    client->GetScriptInterface().SetProperty(msg.get(), "guid", std::string(message->m_GUID), false);
     442    client->GetScriptInterface().SetProperty(msg.get(), "text", int (message->m_Status), false);
     443    client->PushGuiMessage(msg);
     444
     445    return true;
     446}
     447
    422448bool CNetClient::OnGameSetup(void* context, CFsmEvent* event)
    423449{
    424450    ENSURE(event->GetType() == (uint)NMT_GAME_SETUP);
     
    453479        assignment.m_Enabled = true;
    454480        assignment.m_Name = message->m_Hosts[i].m_Name;
    455481        assignment.m_PlayerID = message->m_Hosts[i].m_PlayerID;
     482        assignment.m_Status = message->m_Hosts[i].m_Status;
    456483        newPlayerAssignments[message->m_Hosts[i].m_GUID] = assignment;
    457484    }
    458485
  • source/network/NetClient.h

     
    164164    void LoadFinished();
    165165
    166166    void SendChatMessage(const std::wstring& text);
     167   
     168    void SendReadyMessage(const int status);
    167169
    168170private:
    169171    // Net message / FSM transition handlers
     
    172174    static bool OnHandshakeResponse(void* context, CFsmEvent* event);
    173175    static bool OnAuthenticate(void* context, CFsmEvent* event);
    174176    static bool OnChat(void* context, CFsmEvent* event);
     177    static bool OnReady(void* context, CFsmEvent* event);
    175178    static bool OnGameSetup(void* context, CFsmEvent* event);
    176179    static bool OnPlayerAssignment(void* context, CFsmEvent* event);
    177180    static bool OnInGame(void* context, CFsmEvent* event);
  • source/network/NetHost.h

     
    4646
    4747    /// The player that the given host controls, or -1 if none (observer)
    4848    i32 m_PlayerID;
     49
     50    /// Status - Ready or not: 0 for not ready, 1 for ready
     51    i32 m_Status;
    4952};
    5053
    5154typedef std::map<CStr, PlayerAssignment> PlayerAssignmentMap; // map from GUID -> assignment
  • source/network/NetMessage.cpp

     
    174174    case NMT_CHAT:
    175175        pNewMessage = new CChatMessage;
    176176        break;
     177   
     178    case NMT_READY:
     179        pNewMessage = new CReadyMessage;
     180        break;
    177181
    178182    case NMT_SIMULATION_COMMAND:
    179183        pNewMessage = new CSimulationMessage(scriptInterface);
  • source/network/NetMessages.h

     
    4646    NMT_AUTHENTICATE,       // Authentication stage
    4747    NMT_AUTHENTICATE_RESULT,
    4848    NMT_CHAT,       // Common chat message
     49    NMT_READY,
    4950    NMT_GAME_SETUP,
    5051    NMT_PLAYER_ASSIGNMENT,
    5152
     
    118119    NMT_FIELD(CStrW, m_Message)
    119120END_NMT_CLASS()
    120121
     122START_NMT_CLASS_(Ready, NMT_READY)
     123    NMT_FIELD(CStr8, m_GUID)
     124    NMT_FIELD_INT(m_Status, u8, 1)
     125END_NMT_CLASS()
     126
    121127START_NMT_CLASS_(PlayerAssignment, NMT_PLAYER_ASSIGNMENT)
    122128    NMT_START_ARRAY(m_Hosts)
    123129        NMT_FIELD(CStr8, m_GUID)
    124130        NMT_FIELD(CStrW, m_Name)
    125131        NMT_FIELD_INT(m_PlayerID, i8, 1)
     132        NMT_FIELD_INT(m_Status, u8, 1)
    126133    NMT_END_ARRAY()
    127134END_NMT_CLASS()
    128135
  • source/network/NetServer.cpp

     
    376376
    377377    std::vector<std::pair<int, CStr> > newAssignPlayer;
    378378    std::vector<bool> newStartGame;
     379    std::vector<std::pair<int, CStr> > newPlayerReady;
     380    std::vector<bool> newPlayerResetReady;
    379381    std::vector<std::string> newGameAttributes;
    380382    std::vector<u32> newTurnLength;
    381383
     
    386388            return false;
    387389
    388390        newStartGame.swap(m_StartGameQueue);
     391        newPlayerReady.swap(m_PlayerReadyQueue);
     392        newPlayerResetReady.swap(m_PlayerResetReadyQueue);
    389393        newAssignPlayer.swap(m_AssignPlayerQueue);
    390394        newGameAttributes.swap(m_GameAttributesQueue);
    391395        newTurnLength.swap(m_TurnLengthQueue);
     
    394398    for (size_t i = 0; i < newAssignPlayer.size(); ++i)
    395399        AssignPlayer(newAssignPlayer[i].first, newAssignPlayer[i].second);
    396400
     401    for (size_t i = 0; i < newPlayerReady.size(); ++i)
     402        ReadyPlayer(newPlayerReady[i].first, newPlayerReady[i].second);
     403
     404    if (!newPlayerResetReady.empty())
     405        ClearAllPlayerReady();
     406
    397407    if (!newGameAttributes.empty())
    398408        UpdateGameAttributes(GetScriptInterface().ParseJSON(newGameAttributes.back()));
    399409
     
    548558
    549559    session->AddTransition(NSS_PREGAME, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context);
    550560    session->AddTransition(NSS_PREGAME, (uint)NMT_CHAT, NSS_PREGAME, (void*)&OnChat, context);
     561    session->AddTransition(NSS_PREGAME, (uint)NMT_READY, NSS_PREGAME, (void*)&OnReady, context);
    551562    session->AddTransition(NSS_PREGAME, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnLoadedGame, context);
    552563
    553564    session->AddTransition(NSS_JOIN_SYNCING, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnJoinSyncingLoadedGame, context);
     
    649660    assignment.m_Enabled = true;
    650661    assignment.m_Name = name;
    651662    assignment.m_PlayerID = playerID;
     663    assignment.m_Status = 0;
    652664    m_PlayerAssignments[guid] = assignment;
    653665
    654666    // Send the new assignments to all currently active players
     
    663675    SendPlayerAssignments();
    664676}
    665677
     678void CNetServerWorker::ReadyPlayer(const int ready, const CStr& guid)
     679{
     680    m_PlayerAssignments[guid].m_Status = ready;
     681
     682    SendPlayerAssignments();
     683}
     684
     685void CNetServerWorker::ClearAllPlayerReady()
     686{
     687    for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it)
     688    {
     689        it->second.m_Status = 0;
     690    }
     691
     692    SendPlayerAssignments();
     693}
     694
    666695void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid)
    667696{
    668697    // Remove anyone who's already assigned to this player
     
    690719        h.m_GUID = it->first;
    691720        h.m_Name = it->second.m_Name;
    692721        h.m_PlayerID = it->second.m_PlayerID;
     722        h.m_Status = it->second.m_Status;
    693723        message.m_Hosts.push_back(h);
    694724    }
    695725}
     
    860890    return true;
    861891}
    862892
     893bool CNetServerWorker::OnReady(void* context, CFsmEvent* event)
     894{
     895    ENSURE(event->GetType() == (uint)NMT_READY);
     896
     897    CNetServerSession* session = (CNetServerSession*)context;
     898    CNetServerWorker& server = session->GetServer();
     899
     900    CReadyMessage* message = (CReadyMessage*)event->GetParamRef();
     901
     902    message->m_GUID = session->GetGUID();
     903
     904    server.Broadcast(message);
     905
     906    return true;
     907}
     908
    863909bool CNetServerWorker::OnLoadedGame(void* context, CFsmEvent* event)
    864910{
    865911    ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);
     
    10531099    m_Worker->m_AssignPlayerQueue.push_back(std::make_pair(playerID, guid));
    10541100}
    10551101
     1102void CNetServer::ReadyPlayer(int ready, const CStr& guid)
     1103{
     1104    CScopeLock lock(m_Worker->m_WorkerMutex);
     1105    m_Worker->m_PlayerReadyQueue.push_back(std::make_pair(ready, guid));
     1106}
     1107
     1108void CNetServer::ClearAllPlayerReady()
     1109{
     1110    CScopeLock lock(m_Worker->m_WorkerMutex);
     1111    m_Worker->m_PlayerResetReadyQueue.push_back(false);
     1112}
     1113
    10561114void CNetServer::StartGame()
    10571115{
    10581116    CScopeLock lock(m_Worker->m_WorkerMutex);
  • source/network/NetServer.h

     
    122122     * The changes will be asynchronously propagated to all clients.
    123123     */
    124124    void AssignPlayer(int playerID, const CStr& guid);
     125   
     126    /**
     127     * Call from the GUI to update the player readiness.
     128     * The changes will be asynchronously propagated to all clients.
     129     */
     130    void ReadyPlayer(int ready, const CStr& guid);
    125131
    126132    /**
     133     * Call from the GUI to set the all player readiness to 0.
     134     * The changes will be asynchronously propagated to all clients.
     135     */
     136    void ClearAllPlayerReady();
     137   
     138    /**
    127139     * Call from the GUI to asynchronously notify all clients that they should start loading the game.
    128140     */
    129141    void StartGame();
     
    233245
    234246    void AddPlayer(const CStr& guid, const CStrW& name);
    235247    void RemovePlayer(const CStr& guid);
     248    void ReadyPlayer(const int ready, const CStr& guid);
    236249    void SendPlayerAssignments();
     250    void ClearAllPlayerReady();
    237251
    238252    void SetupSession(CNetServerSession* session);
    239253    bool HandleConnect(CNetServerSession* session);
     
    245259    static bool OnAuthenticate(void* context, CFsmEvent* event);
    246260    static bool OnInGame(void* context, CFsmEvent* event);
    247261    static bool OnChat(void* context, CFsmEvent* event);
     262    static bool OnReady(void* context, CFsmEvent* event);
    248263    static bool OnLoadedGame(void* context, CFsmEvent* event);
    249264    static bool OnJoinSyncingLoadedGame(void* context, CFsmEvent* event);
    250265    static bool OnDisconnect(void* context, CFsmEvent* event);
     
    320335    // Queues for messages sent by the game thread:
    321336    std::vector<std::pair<int, CStr> > m_AssignPlayerQueue; // protected by m_WorkerMutex
    322337    std::vector<bool> m_StartGameQueue; // protected by m_WorkerMutex
     338    std::vector<std::pair<int, CStr> > m_PlayerReadyQueue; // protected by m_WorkerMutex
     339    std::vector<bool> m_PlayerResetReadyQueue; // protected by m_WorkerMutex
    323340    std::vector<std::string> m_GameAttributesQueue; // protected by m_WorkerMutex
    324341    std::vector<u32> m_TurnLengthQueue; // protected by m_WorkerMutex
    325342};