Ticket #2447: readyv4.patch
File readyv4.patch, 29.8 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/gui/common/modern/sprites.xml
296 296 size="0 0 22 22" 297 297 /> 298 298 </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> 299 309 </sprites> -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
31 31 // (and therefore shouldn't send further messages to the network) 32 32 var g_IsInGuiUpdate; 33 33 34 // Is this user ready 35 var g_IsReady; 36 37 // If no one has changed ready status, we have no need to spam the settings changed message. 38 // 2 - Host's initial ready, suppressed settings message, 1 - Will show settings message, <=0 - Suppressed settings message 39 var g_ReadyChanged = 2; 40 34 41 var g_PlayerAssignments = {}; 35 42 36 43 // Default game setup attributes … … 97 104 { 98 105 cancelButton.tooltip = "Return to the lobby." 99 106 } 100 101 107 } 102 108 103 109 // Called after the map data is loaded and cached … … 412 418 break; 413 419 414 420 case "players": 421 var resetReady = false; 422 var newPlayer = ""; 415 423 // Find and report all joinings/leavings 416 424 for (var host in message.hosts) 425 { 417 426 if (! g_PlayerAssignments[host]) 427 { 418 428 addChatMessage({ "type": "connect", "username": message.hosts[host].name }); 429 newPlayer = host; 430 } 431 } 419 432 420 433 for (var host in g_PlayerAssignments) 434 { 421 435 if (! message.hosts[host]) 436 { 422 437 addChatMessage({ "type": "disconnect", "guid": host }); 423 438 playersChanged = "leave"; 439 if (g_PlayerAssignments[host] != -1) 440 resetReady = true; // Observers shouldn't reset ready. 441 } 442 } 443 424 444 // Update the player list 425 445 g_PlayerAssignments = message.hosts; 426 446 updatePlayerList(); 427 447 if (g_PlayerAssignments[newPlayer]) 448 { 449 if (g_PlayerAssignments[newPlayer].player != -1) 450 resetReady = true; 451 } 452 453 if (resetReady) 454 resetReadyData(); // Observers shouldn't reset ready. 455 updateReadyUI(); 428 456 if (g_IsController) 429 457 sendRegisterGameStanza(); 430 458 break; … … 447 475 addChatMessage({ "type": "message", "guid": message.guid, "text": message.text }); 448 476 break; 449 477 478 // Singular client to host message 479 case "ready": 480 g_ReadyChanged -= 1; 481 warn(String(g_ReadyChanged)); 482 if (g_ReadyChanged < 1) 483 { 484 if (parseInt(message.text) == 1) 485 addChatMessage({ "type": "ready", "guid": message.guid, "text": "is ready!"}); 486 else 487 addChatMessage({ "type": "ready", "guid": message.guid, "text": "is not ready."}); 488 } 489 if (!g_IsController) 490 break; 491 g_PlayerAssignments[message.guid].status = (parseInt(message.text) == 1); 492 Engine.AssignNetworkPlayerStatus(parseInt(message.text), message.guid); 493 updateReadyUI(); 494 break; 495 450 496 default: 451 497 error("Unrecognised net message type "+message.type); 452 498 } … … 705 751 if (g_IsNetworked) 706 752 Engine.AssignNetworkPlayer(player, ""); 707 753 else 708 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1 } };754 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1, "ready": 0} }; 709 755 } 710 756 } 711 757 … … 822 868 // Reset player assignments on map change 823 869 if (!g_IsNetworked) 824 870 { // Slot 1 825 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1 } };871 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1, "ready": 0} }; 826 872 } 827 873 else 828 874 { … … 842 888 843 889 function launchGame() 844 890 { 891 if (g_IsNetworked && !g_IsReady) 892 { 893 for (var guid in g_PlayerAssignments) 894 { 895 if (g_PlayerAssignments[guid].name.split(" (")[0] == Engine.ConfigDB_GetValue("user", "playername") && g_PlayerAssignments[guid].player == -1) 896 break; // Observers don't need to be ready. 897 else 898 return; // Host may have changed their own code. 899 } 900 } 845 901 if (g_IsNetworked && !g_IsController) 846 902 { 847 903 error("Only host can start game"); … … 1184 1240 if (i >= numPlayers) 1185 1241 continue; 1186 1242 1187 var pName = Engine.GetGUIObjectByName("playerName["+i+"]"); 1243 var pName = Engine.GetGUIObjectByName("playerName["+i+"]"); 1188 1244 var pCiv = Engine.GetGUIObjectByName("playerCiv["+i+"]"); 1189 1245 var pCivText = Engine.GetGUIObjectByName("playerCivText["+i+"]"); 1190 1246 var pTeam = Engine.GetGUIObjectByName("playerTeam["+i+"]"); … … 1198 1254 // Common to all game types 1199 1255 var color = iColorToString(getSetting(pData, pDefs, "Colour")); 1200 1256 pColor.sprite = "colour:"+color+" 100"; 1201 pName.caption = getSetting(pData, pDefs, "Name"); 1257 pName.caption = getSetting(pData, pDefs, "Name"); 1202 1258 1203 1259 var team = getSetting(pData, pDefs, "Team"); 1204 1260 var civ = getSetting(pData, pDefs, "Civ"); … … 1235 1291 1236 1292 // Game attributes include AI settings, so update the player list 1237 1293 updatePlayerList(); 1294 1295 // We should have everyone confirm that the new settings are acceptable. 1296 resetReadyData(); 1238 1297 } 1239 1298 1240 1299 function updateGameAttributes() … … 1404 1463 swapPlayers(guid, playerSlot); 1405 1464 1406 1465 Engine.SetNetworkGameAttributes(g_GameAttributes); 1466 updateReadyUI(); 1407 1467 } 1408 1468 }; 1409 1469 } … … 1485 1545 1486 1546 function addChatMessage(msg) 1487 1547 { 1488 var username = escapeText(msg.username || g_PlayerAssignments[msg.guid].name); 1489 var message = escapeText(msg.text); 1548 var username = ""; 1549 if (msg.username || g_PlayerAssignments[msg.guid]) 1550 username = escapeText(msg.username || g_PlayerAssignments[msg.guid].name); 1490 1551 1552 var message = ""; 1553 if (msg.text) 1554 message = escapeText(msg.text); 1555 1491 1556 // TODO: Maybe host should have distinct font/color? 1492 1557 var color = "white"; 1493 1558 1494 if (g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != -1) 1495 { // Valid player who has been assigned - get player colour 1496 var player = g_PlayerAssignments[msg.guid].player - 1; 1497 var mapName = g_GameAttributes.map; 1498 var mapData = loadMapData(mapName); 1499 var mapSettings = (mapData && mapData.settings ? mapData.settings : {}); 1500 var pData = mapSettings.PlayerData ? mapSettings.PlayerData[player] : {}; 1501 var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[player] : {}; 1559 if (msg.guid) 1560 { 1561 if (g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != -1) 1562 { // Valid player who has been assigned - get player colour 1563 var player = g_PlayerAssignments[msg.guid].player - 1; 1564 var mapName = g_GameAttributes.map; 1565 var mapData = loadMapData(mapName); 1566 var mapSettings = (mapData && mapData.settings ? mapData.settings : {}); 1567 var pData = mapSettings.PlayerData ? mapSettings.PlayerData[player] : {}; 1568 var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[player] : {}; 1502 1569 1503 color = iColorToString(getSetting(pData, pDefs, "Colour")); 1570 color = iColorToString(getSetting(pData, pDefs, "Colour")); 1571 } 1504 1572 } 1505 1573 1506 1574 var formatted; … … 1518 1586 formatted = '[font="serif-bold-13"]<[color="'+ color +'"]' + username + '[/color]>[/font] ' + message; 1519 1587 break; 1520 1588 1589 case "ready": 1590 formatted = '[font="serif-bold-13"][color="'+ color +'"]*' + username + " " + message + '[/color][/font]'; 1591 break; 1592 1593 case "settings": 1594 formatted = '[font="serif-bold-13"]*The host has changed the settings.[/font]'; 1595 break; 1596 1521 1597 default: 1522 1598 error("Invalid chat message '" + uneval(msg) + "'"); 1523 1599 return; … … 1534 1610 Engine.GetGUIObjectByName("moreOptions").hidden = !Engine.GetGUIObjectByName("moreOptions").hidden; 1535 1611 } 1536 1612 1613 function toggleReady() 1614 { 1615 g_IsReady = !g_IsReady; 1616 if (g_IsReady) 1617 { 1618 Engine.SendNetworkReady(1); 1619 Engine.GetGUIObjectByName("startButton").caption = "I'm not ready."; 1620 } 1621 else 1622 { 1623 Engine.SendNetworkReady(0); 1624 Engine.GetGUIObjectByName("startButton").caption = "I'm ready!"; 1625 } 1626 } 1627 1628 function updateReadyUI() 1629 { 1630 var allReady = true; 1631 for (var guid in g_PlayerAssignments) 1632 { 1633 var pData = g_GameAttributes.settings.PlayerData ? g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1] : {}; 1634 var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[g_PlayerAssignments[guid].player - 1] : {}; 1635 // We don't really care whether observers are ready. 1636 if (g_PlayerAssignments[guid].player == -1) 1637 return; 1638 if (g_PlayerAssignments[guid].status || !g_IsNetworked) 1639 { 1640 // Engine.GetGUIObjectByName("playerReadySprite[" + String(g_PlayerAssignments[guid].player - 1) + "]").sprite = "ModernCheckOn"; 1641 Engine.GetGUIObjectByName("playerName[" + String(g_PlayerAssignments[guid].player - 1)+"]").caption = '[color="0 255 0"]' + getSetting(pData, pDefs, "Name") + '[/color]'; 1642 } 1643 else 1644 { 1645 // Engine.GetGUIObjectByName("playerReadySprite[" + String(g_PlayerAssignments[guid].player - 1) + "]").sprite = "ModernCheckOff"; 1646 Engine.GetGUIObjectByName("playerName[" + String(g_PlayerAssignments[guid].player - 1)+"]").caption = getSetting(pData, pDefs, "Name"); 1647 allReady = false; 1648 } 1649 } 1650 // AIs are always ready. 1651 for (var playerid = 0; playerid < MAX_PLAYERS; playerid++) 1652 { 1653 if (g_GameAttributes.settings.PlayerData[playerid]) 1654 { 1655 var pData = g_GameAttributes.settings.PlayerData ? g_GameAttributes.settings.PlayerData[playerid] : {}; 1656 var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[playerid] : {}; 1657 if (g_GameAttributes.settings.PlayerData[playerid].AI != "" || g_GameAttributes.settings.PlayerData[playerid].Name == "Unassigned") 1658 { 1659 // Engine.GetGUIObjectByName("playerReadySprite[" + String(playerid) + "]").sprite = "ModernCheckOn"; 1660 Engine.GetGUIObjectByName("playerName[" + String(playerid)+"]").caption = '[color="0 255 0"]' + getSetting(pData, pDefs, "Name") + '[/color]'; 1661 } 1662 } 1663 } 1664 1665 // The host is not allowed to start until everyone is ready. 1666 if (g_IsNetworked && g_IsController) 1667 Engine.GetGUIObjectByName("startGame").enabled = allReady; 1668 } 1669 1670 function resetReadyData() 1671 { 1672 if (g_ReadyChanged < 1) 1673 { 1674 addChatMessage({ "type": "settings"}); 1675 } 1676 g_ReadyChanged = 2; 1677 if (g_IsNetworked && g_IsController) 1678 { 1679 Engine.ClearAllPlayerReady(); 1680 g_IsReady = true; 1681 Engine.SendNetworkReady(1); 1682 } 1683 else 1684 g_IsReady = false; 1685 } 1537 1686 //////////////////////////////////////////////////////////////////////////////////////////////// 1538 1687 // Basic map filters API 1539 1688 -
binaries/data/mods/public/gui/gamesetup/gamesetup.xml
14 14 <object style="TitleText" type="text" size="50%-128 4 50%+128 36"> 15 15 Match Setup 16 16 </object> 17 17 18 18 <object type="image" style="ModernDialog" size="50%-190 50%-80 50%+190 50%+80" name="loadingWindow"> 19 19 20 20 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16"> … … 32 32 <action on="Tick"> 33 33 onTick(); 34 34 </action> 35 35 36 36 <!-- Number of Players--> 37 37 <object size="24 26 224 54"> 38 38 … … 40 40 <object size="0 0 150 28"> 41 41 <object size="0 0 100% 100%" type="text" style="ModernRightLabelText">Number of players:</object> 42 42 </object> 43 43 44 44 <!-- Number of Players--> 45 45 <object size="150 0 200 28"> 46 46 <object name="numPlayersText" size="0 0 100% 100%" type="text" style="ModernLeftLabelText"/> … … 53 53 <action on="SelectionChange">selectNumPlayers(this.list_data[this.selected]);</action> 54 54 </object> 55 55 </object> 56 </object> 56 57 57 </object>58 59 58 <!-- Player assignments --> 60 59 <object size="24 59 100%-440 358" type="image" sprite="ModernDarkBoxGold" name="playerAssignmentsPannel"> 61 60 <object size="0 6 100% 30"> 62 61 <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>62 <object name="playerPlacementHeading" type="text" style="ModernLabelText" size="20% 0 50%+35 100%">Player Placement</object> 63 <object name="playerCivHeading" type="text" style="ModernLabelText" size="50%+65 0 85%-26 100%">Civilization</object> 65 64 <object name="civInfoButton" 66 65 type="button" 67 66 sprite="iconInfoGold" 68 67 sprite_over="iconInfoWhite" 69 size=" 82%-8 0 82%+816"68 size="67.5%+68 0 67.5%+84 16" 70 69 tooltip_style="onscreenToolTip" 71 70 tooltip="View civilization info" 72 71 > … … 75 74 ]]></action> 76 75 </object> 77 76 <object name="playerTeamHeading" type="text" style="ModernLabelText" size="85%+5 0 100%-5 100%">Team</object> 77 <!--<object name="playerReadyHeading" type="text" style="ModernLabelText" size="90%+5 0 100%-5 100%">Ready</object>--> 78 78 </object> 79 79 <object size="1 36 100%-1 100%"> 80 80 <repeat count="8"> 81 81 <object name="playerBox[n]" size="0 0 100% 32" hidden="true"> 82 82 <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%+ 56 50%+60 26"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% 2 50%+35 30" tooltip_style="onscreenToolTip" tooltip="Select player."/> 85 <object name="playerConfig[n]" type="button" style="StoneButton" size="50%+40 6 50%+60 26" 86 86 tooltip_style="onscreenToolTip" 87 87 tooltip="Configure AI settings." 88 88 font="serif-bold-stroke-12" 89 > Settings</object>89 >O</object> 90 90 <object name="playerCiv[n]" type="dropdown" style="ModernDropDown" size="50%+65 2 85% 30" tooltip_style="onscreenToolTip" tooltip="Select player's civilization."/> 91 91 <object name="playerCivText[n]" type="text" style="ModernLabelText" size="50%+65 0 85% 30"/> 92 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 93 <object name="playerTeamText[n]" type="text" style="ModernLabelText" size="85%+5 0 100%-5 100%"/> 94 <!--<object name="playerReadySprite[n]" type="image" sprite="ModernCheckOff" size="95%-16 0 95%+16 32"/> --> 94 95 </object> 95 96 </repeat> 96 97 </object> 97 98 </object> 98 <object size="24 64 100%-460 358" type="image" sprite="CoverFillDark" name="playerAssignmentsPan nelCover" hidden="true"/>99 <object size="24 64 100%-460 358" type="image" sprite="CoverFillDark" name="playerAssignmentsPanelCover" hidden="true"/> 99 100 <!-- Map selection --> 100 101 101 102 … … 112 113 <object name="mapSelectionText" type="text" style="ModernLeftLabelText" size="0 64 100% 94" hidden="true"/> 113 114 <object name="mapSizeText" type="text" style="ModernLeftLabelText" size="0 96 100% 126" hidden="true"/> 114 115 </object> 115 116 116 117 <object name="mapTypeSelection" 117 118 type="dropdown" 118 119 style="ModernDropDown" … … 159 160 </object> 160 161 161 162 <!-- Chat window --> 162 <object name="chatPanel" size="24 370 100%-440 100%- 60" type="image" sprite="ModernDarkBoxGold">163 <object name="chatPanel" size="24 370 100%-440 100%-58" type="image" sprite="ModernDarkBoxGold"> 163 164 <object name="chatText" size="2 2 100%-2 100%-26" type="text" style="ChatPanel"/> 164 165 165 166 <object name="chatInput" size="4 100%-24 100%-76 100%-4" type="input" style="ModernInput"> … … 179 180 textcolor="white" 180 181 sprite="BackgroundTranslucent" 181 182 hidden="true" 182 size=" 100%-700 100%-56 100%-312100%-24"183 size="25 100%-56 100%-445 100%-24" 183 184 >[Tooltip text]</object> 184 185 185 <!-- Start Button -->186 <!-- Start/Ready Button --> 186 187 <object 187 188 name="startGame" 188 189 type="button" 189 190 style="StoneButton" 190 size="100%- 308 100%-52 100%-168100%-24"191 size="100%-285 100%-52 100%-165 100%-24" 191 192 tooltip_style="onscreenToolTip" 192 193 tooltip="Start a new game with the current settings." 193 194 enabled="false" 194 195 > 195 196 Start game! 196 <action on="Press">launchGame();</action> 197 <action on="Press"> 198 if (g_IsController) 199 launchGame(); 200 else 201 toggleReady();</action> 197 202 </object> 198 203 199 204 <!-- Cancel Button --> … … 202 207 caption="Back" 203 208 type="button" 204 209 style="StoneButton" 205 size="100%-1 64 100%-52 100%-24100%-24"210 size="100%-145 100%-52 100%-25 100%-24" 206 211 tooltip_style="onscreenToolTip" 207 212 > 208 213 <action on="Press"> … … 215 220 ]]> 216 221 </action> 217 222 </object> 218 223 219 224 <!-- Options --> 220 225 <object name="gameOptionsBox" size="100%-425 497 100%-25 525"> 221 226 <!-- More Options Button --> -
source/gui/scripting/ScriptFunctions.cpp
343 343 g_NetServer->AssignPlayer(playerID, guid); 344 344 } 345 345 346 void AssignNetworkPlayerStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int ready, std::string guid) 347 { 348 ENSURE(g_NetServer); 349 350 g_NetServer->ReadyPlayer(ready, guid); 351 } 352 353 void ClearAllPlayerReady (ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) 354 { 355 ENSURE(g_NetServer); 356 357 g_NetServer->ClearAllPlayerReady(); 358 } 359 346 360 void SendNetworkChat(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring message) 347 361 { 348 362 ENSURE(g_NetClient); … … 350 364 g_NetClient->SendChatMessage(message); 351 365 } 352 366 367 void SendNetworkReady(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int message) 368 { 369 ENSURE(g_NetClient); 370 371 g_NetClient->SendReadyMessage(message); 372 } 373 353 374 std::vector<CScriptValRooted> GetAIs(ScriptInterface::CxPrivate* pCxPrivate) 354 375 { 355 376 return ICmpAIManager::GetAIs(*(pCxPrivate->pScriptInterface)); … … 838 859 scriptInterface.RegisterFunction<CScriptVal, &PollNetworkClient>("PollNetworkClient"); 839 860 scriptInterface.RegisterFunction<void, CScriptVal, &SetNetworkGameAttributes>("SetNetworkGameAttributes"); 840 861 scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer"); 862 scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayerStatus>("AssignNetworkPlayerStatus"); 863 scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady"); 841 864 scriptInterface.RegisterFunction<void, std::wstring, &SendNetworkChat>("SendNetworkChat"); 865 scriptInterface.RegisterFunction<void, int, &SendNetworkReady>("SendNetworkReady"); 842 866 scriptInterface.RegisterFunction<std::vector<CScriptValRooted>, &GetAIs>("GetAIs"); 843 867 scriptInterface.RegisterFunction<CScriptValRooted, &GetEngineInfo>("GetEngineInfo"); 844 868 -
source/network/NetClient.cpp
87 87 AddTransition(NCS_INITIAL_GAMESETUP, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context); 88 88 89 89 AddTransition(NCS_PREGAME, (uint)NMT_CHAT, NCS_PREGAME, (void*)&OnChat, context); 90 AddTransition(NCS_PREGAME, (uint)NMT_READY, NCS_PREGAME, (void*)&OnReady, context); 90 91 AddTransition(NCS_PREGAME, (uint)NMT_GAME_SETUP, NCS_PREGAME, (void*)&OnGameSetup, context); 91 92 AddTransition(NCS_PREGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_PREGAME, (void*)&OnPlayerAssignment, context); 92 93 AddTransition(NCS_PREGAME, (uint)NMT_GAME_START, NCS_LOADING, (void*)&OnGameStart, context); … … 214 215 GetScriptInterface().Eval("({})", host); 215 216 GetScriptInterface().SetProperty(host.get(), "name", std::wstring(it->second.m_Name), false); 216 217 GetScriptInterface().SetProperty(host.get(), "player", it->second.m_PlayerID, false); 218 GetScriptInterface().SetProperty(host.get(), "status", it->second.m_Status, false); 217 219 GetScriptInterface().SetProperty(hosts.get(), it->first.c_str(), host, false); 218 220 } 219 221 … … 254 256 SendMessage(&chat); 255 257 } 256 258 259 void CNetClient::SendReadyMessage(const int status) 260 { 261 CReadyMessage readyStatus; 262 readyStatus.m_Status = status; 263 SendMessage(&readyStatus); 264 } 265 257 266 bool CNetClient::HandleMessage(CNetMessage* message) 258 267 { 259 268 // Handle non-FSM messages first … … 419 428 return true; 420 429 } 421 430 431 bool 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 422 448 bool CNetClient::OnGameSetup(void* context, CFsmEvent* event) 423 449 { 424 450 ENSURE(event->GetType() == (uint)NMT_GAME_SETUP); … … 453 479 assignment.m_Enabled = true; 454 480 assignment.m_Name = message->m_Hosts[i].m_Name; 455 481 assignment.m_PlayerID = message->m_Hosts[i].m_PlayerID; 482 assignment.m_Status = message->m_Hosts[i].m_Status; 456 483 newPlayerAssignments[message->m_Hosts[i].m_GUID] = assignment; 457 484 } 458 485 -
source/network/NetClient.h
164 164 void LoadFinished(); 165 165 166 166 void SendChatMessage(const std::wstring& text); 167 168 void SendReadyMessage(const int status); 167 169 168 170 private: 169 171 // Net message / FSM transition handlers … … 172 174 static bool OnHandshakeResponse(void* context, CFsmEvent* event); 173 175 static bool OnAuthenticate(void* context, CFsmEvent* event); 174 176 static bool OnChat(void* context, CFsmEvent* event); 177 static bool OnReady(void* context, CFsmEvent* event); 175 178 static bool OnGameSetup(void* context, CFsmEvent* event); 176 179 static bool OnPlayerAssignment(void* context, CFsmEvent* event); 177 180 static bool OnInGame(void* context, CFsmEvent* event); -
source/network/NetHost.h
46 46 47 47 /// The player that the given host controls, or -1 if none (observer) 48 48 i32 m_PlayerID; 49 50 /// Status - Ready or not: 0 for not ready, 1 for ready 51 i32 m_Status; 49 52 }; 50 53 51 54 typedef std::map<CStr, PlayerAssignment> PlayerAssignmentMap; // map from GUID -> assignment -
source/network/NetMessage.cpp
174 174 case NMT_CHAT: 175 175 pNewMessage = new CChatMessage; 176 176 break; 177 178 case NMT_READY: 179 pNewMessage = new CReadyMessage; 180 break; 177 181 178 182 case NMT_SIMULATION_COMMAND: 179 183 pNewMessage = new CSimulationMessage(scriptInterface); -
source/network/NetMessages.h
46 46 NMT_AUTHENTICATE, // Authentication stage 47 47 NMT_AUTHENTICATE_RESULT, 48 48 NMT_CHAT, // Common chat message 49 NMT_READY, 49 50 NMT_GAME_SETUP, 50 51 NMT_PLAYER_ASSIGNMENT, 51 52 … … 118 119 NMT_FIELD(CStrW, m_Message) 119 120 END_NMT_CLASS() 120 121 122 START_NMT_CLASS_(Ready, NMT_READY) 123 NMT_FIELD(CStr8, m_GUID) 124 NMT_FIELD_INT(m_Status, u8, 1) 125 END_NMT_CLASS() 126 121 127 START_NMT_CLASS_(PlayerAssignment, NMT_PLAYER_ASSIGNMENT) 122 128 NMT_START_ARRAY(m_Hosts) 123 129 NMT_FIELD(CStr8, m_GUID) 124 130 NMT_FIELD(CStrW, m_Name) 125 131 NMT_FIELD_INT(m_PlayerID, i8, 1) 132 NMT_FIELD_INT(m_Status, u8, 1) 126 133 NMT_END_ARRAY() 127 134 END_NMT_CLASS() 128 135 -
source/network/NetServer.cpp
376 376 377 377 std::vector<std::pair<int, CStr> > newAssignPlayer; 378 378 std::vector<bool> newStartGame; 379 std::vector<std::pair<int, CStr> > newPlayerReady; 380 std::vector<bool> newPlayerResetReady; 379 381 std::vector<std::string> newGameAttributes; 380 382 std::vector<u32> newTurnLength; 381 383 … … 386 388 return false; 387 389 388 390 newStartGame.swap(m_StartGameQueue); 391 newPlayerReady.swap(m_PlayerReadyQueue); 392 newPlayerResetReady.swap(m_PlayerResetReadyQueue); 389 393 newAssignPlayer.swap(m_AssignPlayerQueue); 390 394 newGameAttributes.swap(m_GameAttributesQueue); 391 395 newTurnLength.swap(m_TurnLengthQueue); … … 394 398 for (size_t i = 0; i < newAssignPlayer.size(); ++i) 395 399 AssignPlayer(newAssignPlayer[i].first, newAssignPlayer[i].second); 396 400 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 397 407 if (!newGameAttributes.empty()) 398 408 UpdateGameAttributes(GetScriptInterface().ParseJSON(newGameAttributes.back())); 399 409 … … 548 558 549 559 session->AddTransition(NSS_PREGAME, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context); 550 560 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); 551 562 session->AddTransition(NSS_PREGAME, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnLoadedGame, context); 552 563 553 564 session->AddTransition(NSS_JOIN_SYNCING, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnJoinSyncingLoadedGame, context); … … 649 660 assignment.m_Enabled = true; 650 661 assignment.m_Name = name; 651 662 assignment.m_PlayerID = playerID; 663 assignment.m_Status = 0; 652 664 m_PlayerAssignments[guid] = assignment; 653 665 654 666 // Send the new assignments to all currently active players … … 663 675 SendPlayerAssignments(); 664 676 } 665 677 678 void CNetServerWorker::ReadyPlayer(const int ready, const CStr& guid) 679 { 680 m_PlayerAssignments[guid].m_Status = ready; 681 682 SendPlayerAssignments(); 683 } 684 685 void 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 666 695 void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid) 667 696 { 668 697 // Remove anyone who's already assigned to this player … … 690 719 h.m_GUID = it->first; 691 720 h.m_Name = it->second.m_Name; 692 721 h.m_PlayerID = it->second.m_PlayerID; 722 h.m_Status = it->second.m_Status; 693 723 message.m_Hosts.push_back(h); 694 724 } 695 725 } … … 860 890 return true; 861 891 } 862 892 893 bool 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 863 909 bool CNetServerWorker::OnLoadedGame(void* context, CFsmEvent* event) 864 910 { 865 911 ENSURE(event->GetType() == (uint)NMT_LOADED_GAME); … … 1053 1099 m_Worker->m_AssignPlayerQueue.push_back(std::make_pair(playerID, guid)); 1054 1100 } 1055 1101 1102 void 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 1108 void CNetServer::ClearAllPlayerReady() 1109 { 1110 CScopeLock lock(m_Worker->m_WorkerMutex); 1111 m_Worker->m_PlayerResetReadyQueue.push_back(false); 1112 } 1113 1056 1114 void CNetServer::StartGame() 1057 1115 { 1058 1116 CScopeLock lock(m_Worker->m_WorkerMutex); -
source/network/NetServer.h
122 122 * The changes will be asynchronously propagated to all clients. 123 123 */ 124 124 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); 125 131 126 132 /** 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 /** 127 139 * Call from the GUI to asynchronously notify all clients that they should start loading the game. 128 140 */ 129 141 void StartGame(); … … 233 245 234 246 void AddPlayer(const CStr& guid, const CStrW& name); 235 247 void RemovePlayer(const CStr& guid); 248 void ReadyPlayer(const int ready, const CStr& guid); 236 249 void SendPlayerAssignments(); 250 void ClearAllPlayerReady(); 237 251 238 252 void SetupSession(CNetServerSession* session); 239 253 bool HandleConnect(CNetServerSession* session); … … 245 259 static bool OnAuthenticate(void* context, CFsmEvent* event); 246 260 static bool OnInGame(void* context, CFsmEvent* event); 247 261 static bool OnChat(void* context, CFsmEvent* event); 262 static bool OnReady(void* context, CFsmEvent* event); 248 263 static bool OnLoadedGame(void* context, CFsmEvent* event); 249 264 static bool OnJoinSyncingLoadedGame(void* context, CFsmEvent* event); 250 265 static bool OnDisconnect(void* context, CFsmEvent* event); … … 320 335 // Queues for messages sent by the game thread: 321 336 std::vector<std::pair<int, CStr> > m_AssignPlayerQueue; // protected by m_WorkerMutex 322 337 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 323 340 std::vector<std::string> m_GameAttributesQueue; // protected by m_WorkerMutex 324 341 std::vector<u32> m_TurnLengthQueue; // protected by m_WorkerMutex 325 342 };