Ticket #1950: pausing.patch
File pausing.patch, 14.2 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/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 Engine.GetGUIObjectByName("pauseOverlayNotPausing").hidden = true; 706 699 707 let pauseOverlay = Engine.GetGUIObjectByName("pauseOverlay"); 700 708 701 709 Engine.SetPaused(pauseOverlay.hidden); -
binaries/data/mods/public/gui/session/messages.js
25 25 var g_ChatTimers = []; 26 26 27 27 /** 28 * The list of GUIDs of players who have currently paused the game. 29 */ 30 var g_PausingPlayers = []; 31 32 /** 28 33 * Handle all netmessage types that can occur. 29 34 */ 30 35 var g_NetMessageTypes = { … … 31 36 "netstatus": msg => handleNetStatusMessage(msg), 32 37 "netwarn": msg => addNetworkWarning(msg), 33 38 "players": msg => handlePlayerAssignmentsMessage(msg), 39 "paused": msg => handlePlayerPausedMessage(msg), 34 40 "rejoined": msg => addChatMessage({ "type": "rejoined", "guid": msg.guid }), 35 41 "kicked": msg => addChatMessage({ "type": "system", "text": sprintf(translate("%(username)s has been kicked"), { "username": msg.username }) }), 36 42 "banned": msg => addChatMessage({ "type": "system", "text": sprintf(translate("%(username)s has been banned"), { "username": msg.username }) }), … … 496 502 } 497 503 } 498 504 505 function handlePlayerPausedMessage(message) 506 { 507 // Update list of pausing players. 508 if (message.pause) 509 g_PausingPlayers.push(message.guid); 510 else 511 g_PausingPlayers.splice(g_PausingPlayers.indexOf(message.guid)); 512 513 var pausingListText = ""; 514 515 g_PausingPlayers.forEach(player => { 516 pausingListText += colorizePlayernameByGUID(player) + "\n"; 517 }); 518 519 Engine.GetGUIObjectByName("pausingListText").caption = pausingListText; 520 521 // Display the overlay for players who didn't pause the game. 522 if (g_PausingPlayers.indexOf(Engine.GetPlayerGUID()) == -1) 523 { 524 let pauseOverlay = Engine.GetGUIObjectByName("pauseOverlayNotPausing"); 525 526 closeOpenDialogs(); 527 528 pauseOverlay.hidden = g_PausingPlayers.length == 0 || g_PausingPlayers == null; 529 Engine.PauseLocalSimulation(!pauseOverlay.hidden); 530 } 531 } 532 499 533 function updateChatAddressees() 500 534 { 501 535 let addressees = [ -
binaries/data/mods/public/gui/session/session.xml
192 192 </object> 193 193 194 194 <!-- ================================ ================================ --> 195 <!-- Pause Overlay for other players who have not paused. --> 196 <!-- ================================ ================================ --> 197 <object name="pauseOverlayNotPausing" size="0 0 100% 100%" type="image" sprite="devCommandsBackground" ghost="false" hidden="true" z="0"> 198 <object size="50%-128 50%-20 50%+128 50%+20" type="text" style="PauseText" ghost="true" z="0"> 199 <translatableAttribute id="caption">Game Paused by:</translatableAttribute> 200 </object> 201 202 <object name="pausingListText" size="50%-128 50%+20 50%+128 80%" type="text" style="PausingListText" ghost="true" z="0"/> 203 </object> 204 205 <!-- ================================ ================================ --> 195 206 <!-- Notification Area --> 196 207 <!-- ================================ ================================ --> 197 208 <object name="notificationPanel" type="image" size="50%-300 60 50%+300 120" ghost="true"> -
binaries/data/mods/public/gui/session/styles.xml
19 19 text_valign="center" 20 20 /> 21 21 22 <style name="PausingListText" 23 font="sans-stroke-16" 24 textcolor="white" 25 text_align="center" 26 text_valign="top" 27 /> 28 22 29 <style name="BuildNameText" 23 30 font="sans-stroke-12" 24 31 textcolor="white" -
source/gui/scripting/ScriptFunctions.cpp
780 780 return; 781 781 } 782 782 g_Game->m_Paused = pause; 783 784 // Only send a message over the network if the game is networked. 785 if (g_NetClient) 786 g_NetClient->SendPausedMessage(pause); 787 783 788 #if CONFIG2_AUDIO 784 789 if (g_SoundManager) 785 790 g_SoundManager->Pause(pause); … … 786 791 #endif 787 792 } 788 793 794 // Pause the local simulation (does not send a paused message over the network). 795 void PauseLocalSimulation(ScriptInterface::CxPrivate* pCxPrivate, bool pause) 796 { 797 if (!g_Game) 798 { 799 JS_ReportError(pCxPrivate->pScriptInterface->GetContext(), "Game is not started"); 800 return; 801 } 802 g_Game->m_Paused = pause; 803 804 #if CONFIG2_AUDIO 805 if (g_SoundManager) 806 g_SoundManager->Pause(pause); 807 #endif 808 } 809 789 810 // Return the global frames-per-second value. 790 811 // params: 791 812 // returns: FPS [int] … … 1088 1109 scriptInterface.RegisterFunction<void, &ExitProgram>("Exit"); 1089 1110 scriptInterface.RegisterFunction<bool, &IsPaused>("IsPaused"); 1090 1111 scriptInterface.RegisterFunction<void, bool, &SetPaused>("SetPaused"); 1112 scriptInterface.RegisterFunction<void, bool, &PauseLocalSimulation>("PauseLocalSimulation"); 1091 1113 scriptInterface.RegisterFunction<int, &GetFps>("GetFPS"); 1092 1114 scriptInterface.RegisterFunction<std::wstring, int, &GetBuildTimestamp>("GetBuildTimestamp"); 1093 1115 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 CClientPausedMessage pausedMsg; 715 pausedMsg.m_GUID = session->GetGUID(); 716 pausedMsg.m_Pause = false; 717 Broadcast(&pausedMsg); 718 } 719 707 720 RemovePlayer(session->GetGUID()); 708 721 709 722 if (m_ServerTurnManager && session->GetCurrState() != NSS_JOIN_SYNCING) … … 1206 1219 return true; 1207 1220 } 1208 1221 1222 bool CNetServerWorker::OnClientPaused(void *context, CFsmEvent *event) 1223 { 1224 ENSURE(event->GetType() == (uint)NMT_CLIENT_PAUSED); 1225 1226 CNetServerSession* session = (CNetServerSession*)context; 1227 CNetServerWorker& server = session->GetServer(); 1228 1229 CClientPausedMessage* message = (CClientPausedMessage*)event->GetParamRef(); 1230 1231 message->m_GUID = session->GetGUID(); 1232 1233 // Update the list of pausing players. 1234 std::vector<CStr>::iterator player = std::find(server.m_PausingPlayers.begin(), server.m_PausingPlayers.end(), session->GetGUID()); 1235 1236 if (message->m_Pause) 1237 { 1238 if (player != server.m_PausingPlayers.end()) 1239 { 1240 LOGERROR("Player paused, but is already included in the list of paused players on the server."); 1241 return true; 1242 } 1243 1244 server.m_PausingPlayers.push_back(session->GetGUID()); 1245 } 1246 else 1247 { 1248 if (player == server.m_PausingPlayers.end()) 1249 { 1250 LOGERROR("Player unpaused, but is not included in the list of paused players on the server."); 1251 return true; 1252 } 1253 1254 server.m_PausingPlayers.erase(player); 1255 } 1256 1257 server.Broadcast(message); 1258 1259 return true; 1260 } 1261 1209 1262 void CNetServerWorker::CheckGameLoadStatus(CNetServerSession* changedSession) 1210 1263 { 1211 1264 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;