Ticket #1950: pausing2.patch
File pausing2.patch, 16.0 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/gui/common/functions_global_object.js
149 149 let messages = []; 150 150 let maxTextWidth = 0; 151 151 152 // TODO: Players who paused the game should be added here153 154 152 // Add network warnings 155 153 if (Engine.ConfigDB_GetValue("user", "overlay.netwarnings") == "true") 156 154 { -
binaries/data/mods/public/gui/credits/texts/programming.json
55 55 {"nick": "dumbo"}, 56 56 {"nick": "dvangennip", "name": "Doménique"}, 57 57 {"nick": "Echelon9", "name": "Rhys Kidd"}, 58 {"nick": "echotangoecho"}, 58 59 {"nick": "eihrul", "name": "Lee Salzman"}, 59 60 {"nick": "elexis", "name": "Alexander Heinsius"}, 60 61 {"nick": "EmjeR", "name": "Matthijs de Rijk"}, -
binaries/data/mods/public/gui/session/menu.js
682 682 Engine.SetPaused(true); 683 683 } 684 684 685 /** 686 * Resume the game in single player mode. 687 */ 685 688 function resumeGame() 686 689 { 690 if (g_IsNetworked) 691 return; 692 687 693 Engine.GetGUIObjectByName("pauseButtonText").caption = translate("Pause"); 688 694 Engine.GetGUIObjectByName("pauseOverlay").hidden = true; 689 695 Engine.SetPaused(false); … … 696 702 697 703 closeOpenDialogs(); 698 704 705 if (g_IsNetworked) 706 { 707 if (g_PausingClients.indexOf(Engine.GetPlayerGUID()) == -1) 708 { 709 g_PausingClients.push(Engine.GetPlayerGUID()); 710 Engine.GetGUIObjectByName("pauseButtonText").caption = translate("Resume"); 711 Engine.MultiplayerPause(true); 712 } 713 else 714 { 715 g_PausingClients.splice(g_PausingClients.indexOf(Engine.GetPlayerGUID()), 1); 716 Engine.GetGUIObjectByName("pauseButtonText").caption = translate("Pause"); 717 Engine.MultiplayerPause(false); 718 } 719 720 updatePauseOverlayMultiplayer(); 721 return; 722 } 723 699 724 let pauseOverlay = Engine.GetGUIObjectByName("pauseOverlay"); 700 725 701 726 Engine.SetPaused(pauseOverlay.hidden); -
binaries/data/mods/public/gui/session/messages.js
31 31 "netstatus": msg => handleNetStatusMessage(msg), 32 32 "netwarn": msg => addNetworkWarning(msg), 33 33 "players": msg => handlePlayerAssignmentsMessage(msg), 34 "paused": msg => handlePlayerPausedMessage(msg), 34 35 "rejoined": msg => addChatMessage({ "type": "rejoined", "guid": msg.guid }), 35 36 "kicked": msg => addChatMessage({ "type": "system", "text": sprintf(translate("%(username)s has been kicked"), { "username": msg.username }) }), 36 37 "banned": msg => addChatMessage({ "type": "system", "text": sprintf(translate("%(username)s has been banned"), { "username": msg.username }) }), … … 461 462 if (message.hosts[guid]) 462 463 continue; 463 464 465 if (g_PausingClients.indexOf(guid) != -1) 466 { 467 g_PausingClients.splice(g_PausingClients.indexOf(guid), 1); 468 updatePauseOverlayMultiplayer(); 469 } 470 464 471 addChatMessage({ "type": "disconnect", "guid": guid }); 465 472 466 473 for (let id in g_Players) … … 496 503 } 497 504 } 498 505 506 function handlePlayerPausedMessage(message) 507 { 508 // Update list of pausing players. 509 if (message.pause) 510 g_PausingClients.push(message.guid); 511 else 512 g_PausingClients.splice(g_PausingClients.indexOf(message.guid), 1); 513 514 Engine.SetPaused(message.pause != 0); 515 516 updatePauseOverlayMultiplayer(); 517 } 518 499 519 function updateChatAddressees() 500 520 { 501 521 let addressees = [ -
binaries/data/mods/public/gui/session/session.js
38 38 var g_HasRejoined = false; 39 39 40 40 /** 41 * The list of GUIDs of players who have currently paused the game, if the game is networked. 42 */ 43 var g_PausingClients = []; 44 45 /** 41 46 * The playerID selected in the change perspective tool. 42 47 */ 43 48 var g_ViewedPlayer = Engine.GetPlayerID(); … … 403 408 Engine.GetGUIObjectByName("summaryButton").enabled = g_IsObserver; 404 409 } 405 410 411 function updatePauseOverlayMultiplayer() 412 { 413 // Hide the pause overlay and return if no one paused. 414 if (!g_PausingClients.length) 415 { 416 Engine.GetGUIObjectByName("multiplayerPauseOverlay").hidden = true; 417 return; 418 } 419 420 // Display "Click to Resume Game" if the player paused, and set the action for this. 421 if (g_PausingClients.indexOf(Engine.GetPlayerGUID()) != -1) 422 { 423 Engine.GetGUIObjectByName("multiplayerPauseMessage").hidden = false; 424 Engine.GetGUIObjectByName("multiplayerPauseOverlay").onPress = togglePause; 425 } 426 else 427 { 428 Engine.GetGUIObjectByName("multiplayerPauseMessage").hidden = true; 429 Engine.GetGUIObjectByName("multiplayerPauseOverlay").onPress = function() {}; 430 } 431 432 var playerNames = []; 433 g_PausingClients.forEach(guid => { 434 playerNames.push(colorizePlayernameByGUID(guid)); 435 }); 436 Engine.GetGUIObjectByName("multiplayerPauseText").caption = translate("Game Paused by") + " " + playerNames.join(", "); 437 438 Engine.GetGUIObjectByName("multiplayerPauseOverlay").hidden = false; 439 } 440 406 441 function reportPerformance(time) 407 442 { 408 443 let settings = Engine.GetMapSettings(); -
binaries/data/mods/public/gui/session/session.xml
192 192 </object> 193 193 194 194 <!-- ================================ ================================ --> 195 <!-- Multiplayer Pause Overlay --> 196 <!-- ================================ ================================ --> 197 <object type="button" 198 name="multiplayerPauseOverlay" 199 size="0 0 100% 100%" 200 tooltip_style="sessionToolTip" 201 hidden="true" 202 z="0" 203 > 204 <object size="0 0 100% 100%" type="image" sprite="devCommandsBackground" ghost="true" z="0"/> 205 <object name="multiplayerPauseText" size="50%-256 50%-60 50%+256 50%+60" type="text" style="PauseText" ghost="true" z="0"/> 206 <object name="multiplayerPauseMessage" size="50%-128 50%+60 50%+128 50%+70" type="text" style="PauseMessageText" ghost="true" z="0" hidden="true"> 207 <translatableAttribute id="caption">Click to Resume Game</translatableAttribute> 208 </object> 209 </object> 210 211 <!-- ================================ ================================ --> 195 212 <!-- Notification Area --> 196 213 <!-- ================================ ================================ --> 197 214 <object name="notificationPanel" type="image" size="50%-300 60 50%+300 120" ghost="true"> -
source/gui/scripting/ScriptFunctions.cpp
786 786 #endif 787 787 } 788 788 789 // Pauses the game and notifies the server of the pause. 790 void MultiplayerPause(ScriptInterface::CxPrivate* pCxPrivate, bool pause) 791 { 792 SetPaused(pCxPrivate, pause); 793 794 ENSURE(g_NetClient); 795 g_NetClient->SendPausedMessage(pause); 796 } 797 789 798 // Return the global frames-per-second value. 790 799 // params: 791 800 // returns: FPS [int] … … 1088 1097 scriptInterface.RegisterFunction<void, &ExitProgram>("Exit"); 1089 1098 scriptInterface.RegisterFunction<bool, &IsPaused>("IsPaused"); 1090 1099 scriptInterface.RegisterFunction<void, bool, &SetPaused>("SetPaused"); 1100 scriptInterface.RegisterFunction<void, bool, &MultiplayerPause>("MultiplayerPause"); 1091 1101 scriptInterface.RegisterFunction<int, &GetFps>("GetFPS"); 1092 1102 scriptInterface.RegisterFunction<std::wstring, int, &GetBuildTimestamp>("GetBuildTimestamp"); 1093 1103 scriptInterface.RegisterFunction<JS::Value, std::wstring, &ReadJSONFile>("ReadJSONFile"); -
source/network/NetClient.cpp
121 121 AddTransition(NCS_INGAME, (uint)NMT_KICKED, NCS_INGAME, (void*)&OnKicked, context); 122 122 AddTransition(NCS_INGAME, (uint)NMT_CLIENT_TIMEOUT, NCS_INGAME, (void*)&OnClientTimeout, context); 123 123 AddTransition(NCS_INGAME, (uint)NMT_CLIENT_PERFORMANCE, NCS_INGAME, (void*)&OnClientPerformance, context); 124 AddTransition(NCS_INGAME, (uint)NMT_CLIENT_PAUSED, NCS_INGAME, (void*)&OnClientPaused, context); 124 125 AddTransition(NCS_INGAME, (uint)NMT_CHAT, NCS_INGAME, (void*)&OnChat, context); 125 126 AddTransition(NCS_INGAME, (uint)NMT_GAME_SETUP, NCS_INGAME, (void*)&OnGameSetup, context); 126 127 AddTransition(NCS_INGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_INGAME, (void*)&OnPlayerAssignment, context); … … 340 341 SendMessage(&rejoinedMessage); 341 342 } 342 343 344 void CNetClient::SendPausedMessage(bool pause) 345 { 346 CClientPausedMessage pausedMessage; 347 pausedMessage.m_Pause = pause; 348 SendMessage(&pausedMessage); 349 } 350 343 351 bool CNetClient::HandleMessage(CNetMessage* message) 344 352 { 345 353 // Handle non-FSM messages first … … 725 733 return true; 726 734 } 727 735 736 bool CNetClient::OnClientPaused(void *context, CFsmEvent *event) 737 { 738 ENSURE(event->GetType() == (uint)NMT_CLIENT_PAUSED); 739 740 CNetClient* client = (CNetClient*)context; 741 JSContext* cx = client->GetScriptInterface().GetContext(); 742 CClientPausedMessage* message = (CClientPausedMessage*)event->GetParamRef(); 743 744 JS::RootedValue msg(cx); 745 client->GetScriptInterface().Eval("({ 'type':'paused' })", &msg); 746 client->GetScriptInterface().SetProperty(msg, "pause", message->m_Pause); 747 client->GetScriptInterface().SetProperty(msg, "guid", message->m_GUID); 748 client->PushGuiMessage(msg); 749 750 return true; 751 } 752 728 753 bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event) 729 754 { 730 755 ENSURE(event->GetType() == (uint)NMT_LOADED_GAME); -
source/network/NetClient.h
197 197 */ 198 198 void SendRejoinedMessage(); 199 199 200 /** 201 * Call when the client has paused or unpaused the game. 202 */ 203 void SendPausedMessage(bool pause); 204 200 205 private: 201 206 // Net message / FSM transition handlers 202 207 static bool OnConnect(void* context, CFsmEvent* event); … … 215 220 static bool OnKicked(void* context, CFsmEvent* event); 216 221 static bool OnClientTimeout(void* context, CFsmEvent* event); 217 222 static bool OnClientPerformance(void* context, CFsmEvent* event); 223 static bool OnClientPaused(void* context, CFsmEvent* event); 218 224 static bool OnLoadedGame(void* context, CFsmEvent* event); 219 225 220 226 /** -
source/network/NetMessage.cpp
147 147 pNewMessage = new CClientPerformanceMessage; 148 148 break; 149 149 150 case NMT_CLIENT_PAUSED: 151 pNewMessage = new CClientPausedMessage; 152 break; 153 150 154 case NMT_LOADED_GAME: 151 155 pNewMessage = new CLoadedGameMessage; 152 156 break; -
source/network/NetMessages.h
28 28 29 29 #define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?' 30 30 #define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!' 31 #define PS_PROTOCOL_VERSION 0x0101001 1// Arbitrary protocol31 #define PS_PROTOCOL_VERSION 0x01010012 // Arbitrary protocol 32 32 #define PS_DEFAULT_PORT 0x5073 // 'P', 's' 33 33 34 34 // Defines the list of message types. The order of the list must not change. … … 62 62 63 63 NMT_CLIENT_TIMEOUT, 64 64 NMT_CLIENT_PERFORMANCE, 65 NMT_CLIENT_PAUSED, 65 66 66 67 NMT_LOADED_GAME, 67 68 NMT_GAME_START, … … 182 183 NMT_END_ARRAY() 183 184 END_NMT_CLASS() 184 185 186 START_NMT_CLASS_(ClientPaused, NMT_CLIENT_PAUSED) 187 NMT_FIELD(CStr, m_GUID) 188 NMT_FIELD_INT(m_Pause, u8, 1) 189 END_NMT_CLASS() 190 185 191 START_NMT_CLASS_(LoadedGame, NMT_LOADED_GAME) 186 192 NMT_FIELD_INT(m_CurrentTurn, u32, 4) 187 193 END_NMT_CLASS() -
source/network/NetServer.cpp
661 661 session->AddTransition(NSS_JOIN_SYNCING, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnJoinSyncingLoadedGame, context); 662 662 663 663 session->AddTransition(NSS_INGAME, (uint)NMT_REJOINED, NSS_INGAME, (void*)&OnRejoined, context); 664 session->AddTransition(NSS_INGAME, (uint)NMT_CLIENT_PAUSED, NSS_INGAME, (void*)&OnClientPaused, context); 664 665 session->AddTransition(NSS_INGAME, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context); 665 666 session->AddTransition(NSS_INGAME, (uint)NMT_CHAT, NSS_INGAME, (void*)&OnChat, context); 666 667 session->AddTransition(NSS_INGAME, (uint)NMT_SIMULATION_COMMAND, NSS_INGAME, (void*)&OnInGame, context); … … 704 705 705 706 void CNetServerWorker::OnUserLeave(CNetServerSession* session) 706 707 { 708 std::vector<CStr>::iterator pausing = std::find(m_PausingPlayers.begin(), m_PausingPlayers.end(), session->GetGUID()); 709 if (pausing != m_PausingPlayers.end()) 710 { 711 // Unpause for the leaving player. 712 m_PausingPlayers.erase(pausing); 713 } 714 707 715 RemovePlayer(session->GetGUID()); 708 716 709 717 if (m_ServerTurnManager && session->GetCurrState() != NSS_JOIN_SYNCING) … … 1174 1182 loaded.m_CurrentTurn = readyTurn; 1175 1183 session->SendMessage(&loaded); 1176 1184 1185 // Send all pausing players to the client. 1186 for (const CStr& guid : server.m_PausingPlayers) 1187 { 1188 CClientPausedMessage pausedMessage; 1189 pausedMessage.m_GUID = guid; 1190 pausedMessage.m_Pause = true; 1191 session->SendMessage(&pausedMessage); 1192 } 1193 1177 1194 return true; 1178 1195 } 1179 1196 … … 1206 1223 return true; 1207 1224 } 1208 1225 1226 bool CNetServerWorker::OnClientPaused(void *context, CFsmEvent *event) 1227 { 1228 ENSURE(event->GetType() == (uint)NMT_CLIENT_PAUSED); 1229 1230 CNetServerSession* session = (CNetServerSession*)context; 1231 CNetServerWorker& server = session->GetServer(); 1232 1233 CClientPausedMessage* message = (CClientPausedMessage*)event->GetParamRef(); 1234 1235 message->m_GUID = session->GetGUID(); 1236 1237 // Update the list of pausing players. 1238 std::vector<CStr>::iterator player = std::find(server.m_PausingPlayers.begin(), server.m_PausingPlayers.end(), session->GetGUID()); 1239 1240 if (message->m_Pause) 1241 { 1242 if (player != server.m_PausingPlayers.end()) 1243 return true; 1244 1245 server.m_PausingPlayers.push_back(session->GetGUID()); 1246 } 1247 else 1248 { 1249 if (player == server.m_PausingPlayers.end()) 1250 return true; 1251 1252 server.m_PausingPlayers.erase(player); 1253 } 1254 1255 // Send messages to clients that are in game, and are not the client who paused. 1256 for (CNetServerSession* session : server.m_Sessions) 1257 { 1258 if (session->GetCurrState() == NSS_INGAME && message->m_GUID != session->GetGUID()) 1259 session->SendMessage(message); 1260 } 1261 1262 return true; 1263 } 1264 1209 1265 void CNetServerWorker::CheckGameLoadStatus(CNetServerSession* changedSession) 1210 1266 { 1211 1267 for (const CNetServerSession* session : m_Sessions) -
source/network/NetServer.h
274 274 static bool OnJoinSyncingLoadedGame(void* context, CFsmEvent* event); 275 275 static bool OnRejoined(void* context, CFsmEvent* event); 276 276 static bool OnDisconnect(void* context, CFsmEvent* event); 277 static bool OnClientPaused(void* context, CFsmEvent* event); 277 278 278 279 void CheckGameLoadStatus(CNetServerSession* changedSession); 279 280 … … 316 317 std::vector<CStr> m_BannedIPs; 317 318 std::vector<CStrW> m_BannedPlayers; 318 319 320 /** 321 * Holds the GUIDs of all currently paused players. 322 */ 323 std::vector<CStr> m_PausingPlayers; 324 319 325 u32 m_NextHostID; 320 326 321 327 CNetServerTurnManager* m_ServerTurnManager;