Ticket #2447: readyv5.patch
File readyv5.patch, 35.6 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/art/textures/ui/global/modern/gear-hover.png
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
-
binaries/data/mods/public/art/textures/ui/global/modern/gear-press.png
Property changes on: binaries/data/mods/public/art/textures/ui/global/modern/gear-hover.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
-
binaries/data/mods/public/art/textures/ui/global/modern/gear.png
Property changes on: binaries/data/mods/public/art/textures/ui/global/modern/gear-press.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
-
binaries/data/mods/public/gui/common/modern/sprites.xml
Property changes on: binaries/data/mods/public/art/textures/ui/global/modern/gear.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property
271 271 <sprite name = "ModernDropDownArrow"> 272 272 <image texture = "global/modern/dropdown-arrow.png" 273 273 real_texture_placement = "0 0 16 16" 274 texture_size="0 0 16 16" 275 size="0 6 16 22" 274 276 /> 275 277 </sprite> 276 278 <sprite name = "ModernDropDownArrowHighlight"> 277 279 <image texture = "global/modern/dropdown-arrow.png" 278 280 real_texture_placement = "0 0 16 16" 281 texture_size="0 0 16 16" 282 size="0 6 16 22" 279 283 /> 280 284 </sprite> 281 285 <sprite name="ModernTickOn"> … … 296 300 size="0 0 22 22" 297 301 /> 298 302 </sprite> 303 <sprite name="ModernGear"> 304 <image texture="global/modern/gear.png" 305 texture_size="0 0 24 24" 306 /> 307 </sprite> 308 <sprite name="ModernGearHover"> 309 <image texture="global/modern/gear-hover.png" 310 texture_size="0 0 24 24" 311 /> 312 </sprite> 313 <sprite name="ModernGearPressed"> 314 <image texture="global/modern/gear-press.png" 315 texture_size="0 0 24 24" 316 /> 317 </sprite> 299 318 </sprites> -
binaries/data/mods/public/gui/common/modern/styles.xml
46 46 sprite2_pressed="ModernDropDownArrowHighlight" 47 47 48 48 buffer_zone="8" 49 dropdown_size="2 16"49 dropdown_size="224" 50 50 sprite_list="colour:12 12 12" 51 51 sprite_selectarea="ModernDarkBoxWhite" 52 52 textcolor_selected="white" -
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 // There are some duplicate orders on init, we can ignore these [bool]. 38 var g_ReadyInit = true; 39 40 // If no one has changed ready status, we have no need to spam the settings changed message. 41 // 2 - Host's initial ready, suppressed settings message, 1 - Will show settings message, <=0 - Suppressed settings message 42 var g_ReadyChanged = 2; 43 44 // Has the game started? 45 var g_GameStarted = false; 46 34 47 var g_PlayerAssignments = {}; 35 48 36 49 // Default game setup attributes … … 98 111 { 99 112 cancelButton.tooltip = translate("Return to the lobby."); 100 113 } 101 102 114 } 103 115 104 116 // Called after the map data is loaded and cached … … 296 308 } 297 309 298 310 Engine.GetGUIObjectByName("numPlayersSelection").hidden = true; 311 Engine.GetGUIObjectByName("startGame").enabled = true; 299 312 } 300 313 301 314 // Set up multiplayer/singleplayer bits: … … 414 427 break; 415 428 416 429 case "players": 430 var resetReady = false; 431 var newPlayer = ""; 417 432 // Find and report all joinings/leavings 418 433 for (var host in message.hosts) 434 { 419 435 if (! g_PlayerAssignments[host]) 436 { 420 437 addChatMessage({ "type": "connect", "username": message.hosts[host].name }); 438 newPlayer = host; 439 } 440 } 421 441 422 442 for (var host in g_PlayerAssignments) 443 { 423 444 if (! message.hosts[host]) 445 { 424 446 addChatMessage({ "type": "disconnect", "guid": host }); 447 if (g_PlayerAssignments[host].player != -1) 448 resetReady = true; // Observers shouldn't reset ready. 449 } 450 } 425 451 426 452 // Update the player list 427 453 g_PlayerAssignments = message.hosts; 428 454 updatePlayerList(); 455 if (g_PlayerAssignments[newPlayer] && g_PlayerAssignments[newPlayer].player != -1) 456 resetReady = true; 429 457 458 if (resetReady) 459 resetReadyData(); // Observers shouldn't reset ready. 460 updateReadyUI(); 430 461 if (g_IsController) 431 462 sendRegisterGameStanza(); 432 463 break; … … 449 480 addChatMessage({ "type": "message", "guid": message.guid, "text": message.text }); 450 481 break; 451 482 483 // Singular client to host message 484 case "ready": 485 g_ReadyChanged -= 1; 486 if (g_ReadyChanged < 1 && g_PlayerAssignments[message.guid].player != -1) 487 addChatMessage({ "type": "ready", "guid": message.guid, "ready": +message.status == 1 }); 488 if (!g_IsController) 489 break; 490 g_PlayerAssignments[message.guid].status = +message.status == 1; 491 Engine.SetNetworkPlayerStatus(message.guid, +message.status); 492 updateReadyUI(); 493 break; 494 452 495 default: 453 496 error("Unrecognised net message type "+message.type); 454 497 } … … 597 640 case "scenario": 598 641 case "skirmish": 599 642 g_MapData[name] = Engine.LoadMapSettings(name); 600 translateObjectKeys(g_MapData[name], ["Name", "Description"]);601 643 break; 602 644 603 645 case "random": 604 646 if (name == "random") 605 647 g_MapData[name] = { settings: { "Name": translateWithContext("map", "Random"), "Description": translate("Randomly selects a map from the list") } }; 606 648 else 607 {608 649 g_MapData[name] = parseJSONData(name+".json"); 609 translateObjectKeys(g_MapData[name], ["Name", "Description"]);610 }611 650 break; 612 651 613 652 default: … … 711 750 if (g_IsNetworked) 712 751 Engine.AssignNetworkPlayer(player, ""); 713 752 else 714 g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1, "civ": "", "team": -1 } };753 g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1, "civ": "", "team": -1, "ready": 0} }; 715 754 } 716 755 } 717 756 … … 828 867 // Reset player assignments on map change 829 868 if (!g_IsNetworked) 830 869 { // Slot 1 831 g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1, "civ": "", "team": -1 } };870 g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1, "civ": "", "team": -1, "ready": 0} }; 832 871 } 833 872 else 834 873 { … … 861 900 if (g_GameAttributes.map == "random") 862 901 selectMap(Engine.GetGUIObjectByName("mapSelection").list_data[Math.floor(Math.random() * 863 902 (Engine.GetGUIObjectByName("mapSelection").list.length - 1)) + 1]); 864 903 g_GameStarted = true; 865 904 g_GameAttributes.settings.mapType = g_GameAttributes.mapType; 866 905 var numPlayers = g_GameAttributes.settings.PlayerData.length; 867 906 // Assign random civilizations to players with that choice … … 1244 1283 1245 1284 // Game attributes include AI settings, so update the player list 1246 1285 updatePlayerList(); 1286 1287 // We should have everyone confirm that the new settings are acceptable. 1288 resetReadyData(); 1247 1289 } 1248 1290 1249 1291 function updateGameAttributes() … … 1413 1455 swapPlayers(guid, playerSlot); 1414 1456 1415 1457 Engine.SetNetworkGameAttributes(g_GameAttributes); 1458 updateReadyUI(); 1416 1459 } 1417 1460 }; 1418 1461 } … … 1494 1537 1495 1538 function addChatMessage(msg) 1496 1539 { 1497 var username = escapeText(msg.username || g_PlayerAssignments[msg.guid].name); 1498 var message = escapeText(msg.text); 1540 var username = ""; 1541 if (msg.username) 1542 username = escapeText(msg.username); 1543 else if (msg.guid && g_PlayerAssignments[msg.guid]) 1544 username = escapeText(g_PlayerAssignments[msg.guid].name); 1499 1545 1546 var message = ""; 1547 if (msg.text) 1548 message = escapeText(msg.text); 1549 1500 1550 // TODO: Maybe host should have distinct font/color? 1501 1551 var color = "white"; 1502 1552 1503 if (g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != -1) 1504 { // Valid player who has been assigned - get player colour 1553 if (msg.guid && g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != -1) 1554 { 1555 // Valid player who has been assigned - get player colour 1505 1556 var player = g_PlayerAssignments[msg.guid].player - 1; 1506 1557 var mapName = g_GameAttributes.map; 1507 1558 var mapData = loadMapData(mapName); … … 1516 1567 switch (msg.type) 1517 1568 { 1518 1569 case "connect": 1519 var formattedUsername = '[font="sans-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]'1520 formatted = '[color="gold"]' + sprintf(translate("%(username)s has joined"), { username: formattedUsername }) ;1570 var formattedUsername = '[font="sans-bold-13"][color="'+ color +'"]' + username + '[/color][/font]' 1571 formatted = '[color="gold"]' + sprintf(translate("%(username)s has joined"), { username: formattedUsername }) + '[/color]'; 1521 1572 break; 1522 1573 1523 1574 case "disconnect": 1524 var formattedUsername = '[font="sans-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]'1525 formatted = '[color="gold"]' + sprintf(translate("%(username)s has left"), { username: formattedUsername }) ;1575 var formattedUsername = '[font="sans-bold-13"][color="'+ color +'"]' + username + '[/color][/font]' 1576 formatted = '[color="gold"]' + sprintf(translate("%(username)s has left"), { username: formattedUsername }) + '[/color]'; 1526 1577 break; 1527 1578 1528 1579 case "message": … … 1531 1582 formatted = sprintf(translate("%(username)s %(message)s"), { username: formattedUsernamePrefix, message: message }); 1532 1583 break; 1533 1584 1585 case "ready": 1586 var formattedUsername = '[font="sans-bold-13"][color="'+ color +'"]' + username + '[/color][/font]' 1587 if (msg.ready) 1588 formatted = '[color="gold"]*' + sprintf(translate("%(username)s is ready!"), { username: formattedUsername }) + '[/color]'; 1589 else 1590 formatted = '[color="gold"]*' + sprintf(translate("%(username)s is not ready."), { username: formattedUsername }) + '[/color]'; 1591 break; 1592 1593 case "settings": 1594 formatted = '[color="gold"][font="sans-bold-13"]*' + translate('Game settings have been changed.') + '[/font][/color]'; 1595 break; 1596 1534 1597 default: 1535 1598 error(sprintf("Invalid chat message '%(message)s'", { message: uneval(msg) })); 1536 1599 return; … … 1547 1610 Engine.GetGUIObjectByName("moreOptions").hidden = !Engine.GetGUIObjectByName("moreOptions").hidden; 1548 1611 } 1549 1612 1613 function toggleReady() 1614 { 1615 g_IsReady = !g_IsReady; 1616 if (g_IsReady) 1617 { 1618 Engine.SendNetworkReady(1); 1619 Engine.GetGUIObjectByName("startGame").caption = translate("I'm not ready."); 1620 Engine.GetGUIObjectByName("startGame").tooltip = translate("State that you are not ready to play."); 1621 } 1622 else 1623 { 1624 Engine.SendNetworkReady(0); 1625 Engine.GetGUIObjectByName("startGame").caption = translate("I'm ready!"); 1626 Engine.GetGUIObjectByName("startGame").tooltip = translate("State that you are ready to play!"); 1627 } 1628 } 1629 1630 function updateReadyUI() 1631 { 1632 var allReady = true; 1633 for (var guid in g_PlayerAssignments) 1634 { 1635 // We don't really care whether observers are ready. 1636 if (g_PlayerAssignments[guid].player == -1 || !g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1]) 1637 continue; 1638 var pData = g_GameAttributes.settings.PlayerData ? g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1] : {}; 1639 var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[g_PlayerAssignments[guid].player - 1] : {}; 1640 if (g_PlayerAssignments[guid].status || !g_IsNetworked) 1641 Engine.GetGUIObjectByName("playerName[" + (g_PlayerAssignments[guid].player - 1) + "]").caption = '[color="0 255 0"]' + getSetting(pData, pDefs, "Name") + '[/color]'; 1642 else 1643 { 1644 Engine.GetGUIObjectByName("playerName[" + (g_PlayerAssignments[guid].player - 1) + "]").caption = getSetting(pData, pDefs, "Name"); 1645 allReady = false; 1646 } 1647 } 1648 // AIs are always ready. 1649 for (var playerid = 0; playerid < MAX_PLAYERS; playerid++) 1650 { 1651 if (!g_GameAttributes.settings.PlayerData[playerid]) 1652 continue; 1653 var pData = g_GameAttributes.settings.PlayerData ? g_GameAttributes.settings.PlayerData[playerid] : {}; 1654 var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[playerid] : {}; 1655 if (g_GameAttributes.settings.PlayerData[playerid].AI != "" || g_GameAttributes.settings.PlayerData[playerid].Name == "Unassigned") 1656 Engine.GetGUIObjectByName("playerName[" + playerid + "]").caption = '[color="0 255 0"]' + getSetting(pData, pDefs, "Name") + '[/color]'; 1657 } 1658 // The host is not allowed to start until everyone is ready. 1659 if (g_IsNetworked && g_IsController) 1660 Engine.GetGUIObjectByName("startGame").enabled = allReady; 1661 } 1662 1663 function resetReadyData() 1664 { 1665 if (g_GameStarted) 1666 return; 1667 if (g_ReadyChanged < 1) 1668 addChatMessage({ "type": "settings"}); 1669 else if (g_ReadyChanged == 2 && !g_ReadyInit) 1670 return; // duplicate calls on init 1671 else 1672 g_ReadyInit = false; 1673 g_ReadyChanged = 2; 1674 if (g_IsNetworked && g_IsController) 1675 { 1676 Engine.ClearAllPlayerReady(); 1677 g_IsReady = true; 1678 Engine.SendNetworkReady(1); 1679 } 1680 else 1681 { 1682 g_IsReady = false; 1683 Engine.GetGUIObjectByName("startGame").caption = translate("I'm ready!"); 1684 Engine.GetGUIObjectByName("startGame").tooltip = translate("State that you accept the current settings and are ready to play!"); 1685 } 1686 } 1550 1687 //////////////////////////////////////////////////////////////////////////////////////////////// 1551 1688 // Basic map filters API 1552 1689 -
binaries/data/mods/public/gui/gamesetup/gamesetup.xml
14 14 <object style="TitleText" type="text" size="50%-128 4 50%+128 36"> 15 15 <translatableAttribute id="caption">Match Setup</translatableAttribute> 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 <object size="24 26 224 54">37 <object size="24 26 100%-24 54"> 38 38 39 39 <!-- Number of Players--> 40 <object size="0 0 150 28">40 <object size="0 0 50%-170 28"> 41 41 <object size="0 0 100% 100%" type="text" style="ModernRightLabelText"> 42 42 <translatableAttribute id="caption">Number of players:</translatableAttribute> 43 43 </object> 44 44 </object> 45 45 46 46 <!-- Number of Players--> 47 <object size=" 150 0 200 28">47 <object size="50%-170 0 50%-120 28"> 48 48 <object name="numPlayersText" size="0 0 100% 100%" type="text" style="ModernLeftLabelText"/> 49 49 <object name="numPlayersSelection" 50 50 type="dropdown" … … 61 61 <!-- Player assignments --> 62 62 <object size="24 59 100%-440 358" type="image" sprite="ModernDarkBoxGold" name="playerAssignmentsPannel"> 63 63 <object size="0 6 100% 30"> 64 <object name="playerNameHeading" type="text" style="ModernLabelText" size="0 0 2 0% 100%">64 <object name="playerNameHeading" type="text" style="ModernLabelText" size="0 0 22% 100%"> 65 65 <translatableAttribute id="caption">Player Name</translatableAttribute> 66 66 </object> 67 <object name="playerPlacementHeading" type="text" style="ModernLabelText" size="2 0%+5 0 50%100%">67 <object name="playerPlacementHeading" type="text" style="ModernLabelText" size="22%+5 0 50%+35 100%"> 68 68 <translatableAttribute id="caption">Player Placement</translatableAttribute> 69 69 </object> 70 <object name="playerCivHeading" type="text" style="ModernLabelText" size="50%+65 0 85% 100%">70 <object name="playerCivHeading" type="text" style="ModernLabelText" size="50%+65 0 85%-26 100%"> 71 71 <translatableAttribute id="caption">Civilization</translatableAttribute> 72 72 </object> 73 73 <object name="civInfoButton" 74 74 type="button" 75 75 sprite="iconInfoGold" 76 76 sprite_over="iconInfoWhite" 77 size=" 82%-8 0 82%+816"77 size="67.5%+68 0 67.5%+84 16" 78 78 tooltip_style="onscreenToolTip" 79 79 > 80 80 <translatableAttribute id="tooltip">View civilization info</translatableAttribute> … … 90 90 <repeat count="8"> 91 91 <object name="playerBox[n]" size="0 0 100% 32" hidden="true"> 92 92 <object name="playerColour[n]" type="image" size="0 0 100% 100%"/> 93 <object name="playerName[n]" type="text" style="ModernLabelText" size="0 2 2 0% 30"/>94 <object name="playerAssignment[n]" type="dropdown" style="ModernDropDown" size="2 0%+5 2 50%30" tooltip_style="onscreenToolTip">93 <object name="playerName[n]" type="text" style="ModernLabelText" size="0 2 22% 30"/> 94 <object name="playerAssignment[n]" type="dropdown" style="ModernDropDown" size="22%+5 2 50%+35 30" tooltip_style="onscreenToolTip"> 95 95 <translatableAttribute id="tooltip">Select player.</translatableAttribute> 96 96 </object> 97 <object name="playerConfig[n]" type="button" style="StoneButton" size="50%+ 5 6 50%+60 26"97 <object name="playerConfig[n]" type="button" style="StoneButton" size="50%+40 4 50%+64 28" 98 98 tooltip_style="onscreenToolTip" 99 99 font="sans-bold-stroke-12" 100 sprite="ModernGear" 101 sprite_over="ModernGearHover" 102 sprite_pressed="ModernGearPressed" 100 103 > 101 <translatableAttribute id="caption">Settings</translatableAttribute>102 104 <translatableAttribute id="tooltip">Configure AI settings.</translatableAttribute> 103 105 </object> 104 <object name="playerCiv[n]" type="dropdown" style="ModernDropDown" size="50%+6 52 85% 30" tooltip_style="onscreenToolTip">106 <object name="playerCiv[n]" type="dropdown" style="ModernDropDown" size="50%+69 2 85% 30" tooltip_style="onscreenToolTip"> 105 107 <translatableAttribute id="tooltip">Select player's civilization.</translatableAttribute> 106 108 </object> 107 109 <object name="playerCivText[n]" type="text" style="ModernLabelText" size="50%+65 0 85% 30"/> … … 113 115 </repeat> 114 116 </object> 115 117 </object> 116 <object size="24 64 100%-460 358" type="image" sprite="CoverFillDark" name="playerAssignmentsPan nelCover" hidden="true"/>118 <object size="24 64 100%-460 358" type="image" sprite="CoverFillDark" name="playerAssignmentsPanelCover" hidden="true"/> 117 119 <!-- Map selection --> 118 120 119 121 … … 138 140 <object name="mapSelectionText" type="text" style="ModernLeftLabelText" size="0 64 100% 94" hidden="true"/> 139 141 <object name="mapSizeText" type="text" style="ModernLeftLabelText" size="0 96 100% 126" hidden="true"/> 140 142 </object> 141 143 142 144 <object name="mapTypeSelection" 143 145 type="dropdown" 144 146 style="ModernDropDown" … … 169 171 </object> 170 172 </object> 171 173 172 <object name="mapSize" size="100%-3 25 459 100%-25 487" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">174 <object name="mapSize" size="100%-315 459 100%-25 487" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip"> 173 175 <translatableAttribute id="tooltip">Select map size. (Larger sizes may reduce performance.)</translatableAttribute> 174 176 </object> 175 177 … … 187 189 </object> 188 190 189 191 <!-- Chat window --> 190 <object name="chatPanel" size="24 370 100%-440 100%- 60" type="image" sprite="ModernDarkBoxGold">192 <object name="chatPanel" size="24 370 100%-440 100%-58" type="image" sprite="ModernDarkBoxGold"> 191 193 <object name="chatText" size="2 2 100%-2 100%-26" type="text" style="ChatPanel"/> 192 194 193 195 <object name="chatInput" size="4 100%-24 100%-76 100%-4" type="input" style="ModernInput"> … … 207 209 textcolor="white" 208 210 sprite="BackgroundTranslucent" 209 211 hidden="true" 210 size=" 100%-700 100%-56 100%-312 100%-24"212 size="20 100%-56 100%-312 100%-24" 211 213 > 212 214 <translatableAttribute id="caption">[Tooltip text]</translatableAttribute> 213 215 </object> 214 216 215 <!-- Start Button -->217 <!-- Start/Ready Button --> 216 218 <object 217 219 name="startGame" 218 220 type="button" … … 223 225 > 224 226 <translatableAttribute id="caption">Start game!</translatableAttribute> 225 227 <translatableAttribute id="tooltip">Start a new game with the current settings.</translatableAttribute> 226 <action on="Press">launchGame();</action> 228 <action on="Press"> 229 if (g_IsController) 230 launchGame(); 231 else 232 toggleReady(); 233 </action> 227 234 </object> 228 235 229 236 <!-- Cancel Button --> … … 245 252 ]]> 246 253 </action> 247 254 </object> 248 255 249 256 <!-- Options --> 250 257 <object name="gameOptionsBox" size="100%-425 497 100%-25 525"> 251 258 <!-- More Options Button --> -
source/gui/scripting/ScriptFunctions.cpp
344 344 g_NetServer->AssignPlayer(playerID, guid); 345 345 } 346 346 347 void SetNetworkPlayerStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string guid, int ready) 348 { 349 ENSURE(g_NetServer); 350 351 g_NetServer->SetPlayerReady(guid, ready); 352 } 353 354 void ClearAllPlayerReady (ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) 355 { 356 ENSURE(g_NetServer); 357 358 g_NetServer->ClearAllPlayerReady(); 359 } 360 347 361 void SendNetworkChat(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring message) 348 362 { 349 363 ENSURE(g_NetClient); … … 351 365 g_NetClient->SendChatMessage(message); 352 366 } 353 367 368 void SendNetworkReady(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int message) 369 { 370 ENSURE(g_NetClient); 371 372 g_NetClient->SendReadyMessage(message); 373 } 374 354 375 std::vector<CScriptValRooted> GetAIs(ScriptInterface::CxPrivate* pCxPrivate) 355 376 { 356 377 return ICmpAIManager::GetAIs(*(pCxPrivate->pScriptInterface)); … … 861 882 scriptInterface.RegisterFunction<CScriptVal, &PollNetworkClient>("PollNetworkClient"); 862 883 scriptInterface.RegisterFunction<void, CScriptVal, &SetNetworkGameAttributes>("SetNetworkGameAttributes"); 863 884 scriptInterface.RegisterFunction<void, int, std::string, &AssignNetworkPlayer>("AssignNetworkPlayer"); 885 scriptInterface.RegisterFunction<void, std::string, int, &SetNetworkPlayerStatus>("SetNetworkPlayerStatus"); 886 scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady"); 864 887 scriptInterface.RegisterFunction<void, std::wstring, &SendNetworkChat>("SendNetworkChat"); 888 scriptInterface.RegisterFunction<void, int, &SendNetworkReady>("SendNetworkReady"); 865 889 scriptInterface.RegisterFunction<std::vector<CScriptValRooted>, &GetAIs>("GetAIs"); 866 890 scriptInterface.RegisterFunction<CScriptValRooted, &GetEngineInfo>("GetEngineInfo"); 867 891 -
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(), "status", 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 u8 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<CStr, int> > 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 SetPlayerReady(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::SetPlayerReady(const CStr& guid, const int ready) 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 it->second.m_Status = 0; 689 690 SendPlayerAssignments(); 691 } 692 666 693 void CNetServerWorker::AssignPlayer(int playerID, const CStr& guid) 667 694 { 668 695 // Remove anyone who's already assigned to this player … … 690 717 h.m_GUID = it->first; 691 718 h.m_Name = it->second.m_Name; 692 719 h.m_PlayerID = it->second.m_PlayerID; 720 h.m_Status = it->second.m_Status; 693 721 message.m_Hosts.push_back(h); 694 722 } 695 723 } … … 860 888 return true; 861 889 } 862 890 891 bool CNetServerWorker::OnReady(void* context, CFsmEvent* event) 892 { 893 ENSURE(event->GetType() == (uint)NMT_READY); 894 895 CNetServerSession* session = (CNetServerSession*)context; 896 CNetServerWorker& server = session->GetServer(); 897 898 CReadyMessage* message = (CReadyMessage*)event->GetParamRef(); 899 900 message->m_GUID = session->GetGUID(); 901 902 server.Broadcast(message); 903 904 return true; 905 } 906 863 907 bool CNetServerWorker::OnLoadedGame(void* context, CFsmEvent* event) 864 908 { 865 909 ENSURE(event->GetType() == (uint)NMT_LOADED_GAME); … … 1053 1097 m_Worker->m_AssignPlayerQueue.push_back(std::make_pair(playerID, guid)); 1054 1098 } 1055 1099 1100 void CNetServer::SetPlayerReady(const CStr& guid, int ready) 1101 { 1102 CScopeLock lock(m_Worker->m_WorkerMutex); 1103 m_Worker->m_PlayerReadyQueue.push_back(std::make_pair(guid, ready)); 1104 } 1105 1106 void CNetServer::ClearAllPlayerReady() 1107 { 1108 CScopeLock lock(m_Worker->m_WorkerMutex); 1109 m_Worker->m_PlayerResetReadyQueue.push_back(false); 1110 } 1111 1056 1112 void CNetServer::StartGame() 1057 1113 { 1058 1114 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 SetPlayerReady(const CStr& guid, int ready); 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 SetPlayerReady(const CStr& guid, const int ready); 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<CStr, int> > 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 }; -
source/network/fsm.cpp
402 402 403 403 // Lookup transition 404 404 CFsmTransition* pTransition = GetTransition( m_CurrState, eventType ); 405 if ( !pTransition ) return false; 405 if ( !pTransition ) 406 return false; 406 407 407 408 // Setup event parameter 408 409 EventMap::iterator it = m_Events.find( eventType ); … … 413 414 } 414 415 415 416 // Valid transition? 416 if ( !pTransition->ApplyConditions() ) return false; 417 if ( !pTransition->ApplyConditions() ) 418 return false; 417 419 418 420 // Save the default state transition (actions might call SetNextState 419 421 // to override this) 420 422 SetNextState( pTransition->GetNextState() ); 421 423 422 424 // Run transition actions 423 if ( !pTransition->RunActions() ) return false; 425 if ( !pTransition->RunActions() ) 426 return false; 424 427 425 428 // Switch state 426 429 SetCurrState( GetNextState() );