Ticket #3242: t3242_observer_late_join_v2.patch
File t3242_observer_late_join_v2.patch, 11.5 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/common/network.js
4 4 switch (id) 5 5 { 6 6 case 0: return translate("Unknown reason"); 7 7 case 1: return translate("Unexpected shutdown"); 8 8 case 2: return translate("Incorrect network protocol version"); 9 case 3: return translate("Game has already started"); 9 case 3: return translate("Game is loading, please try later"); 10 case 4: return translate("Game has already started and the host doesn't allow you to join as obsever"); 10 11 default: return sprintf(translate("\\[Invalid value %(id)s]"), { id: id }); 11 12 } 12 13 } 13 14 14 15 function reportDisconnect(reason) -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
152 152 var mapFilters = Engine.GetGUIObjectByName("mapFilterSelection"); 153 153 mapFilters.list = getFilterNames(); 154 154 mapFilters.list_data = getFilterIds(); 155 155 g_GameAttributes.mapFilter = "default"; 156 156 157 // For singleplayer reduce the size of more options dialog by three options (cheats, rated game, observer late join = 90px) 158 if (!g_IsNetworked) 159 { 160 Engine.GetGUIObjectByName("moreOptions").size = "50%-200 50%-195 50%+200 50%+160"; 161 Engine.GetGUIObjectByName("hideMoreOptions").size = "50%-70 310 50%+70 336"; 162 } 163 // For non-lobby multiplayergames reduce the size of the dialog by one option (rated game, 30px) 164 else if (g_IsNetworked && !Engine.HasXmppClient()) 165 { 166 Engine.GetGUIObjectByName("moreOptions").size = "50%-200 50%-195 50%+200 50%+220"; 167 Engine.GetGUIObjectByName("hideMoreOptions").size = "50%-70 370 50%+70 396"; 168 Engine.GetGUIObjectByName("optionObserverLateJoin").size = "14 338 94% 366"; 169 } 170 157 171 // Setup controls for host only 158 172 if (g_IsController) 159 173 { 160 174 mapTypes.selected = 0; 161 175 mapFilters.selected = 0; … … 253 267 Engine.GetGUIObjectByName("exploreMap").onPress = function() { 254 268 g_GameAttributes.settings.ExploreMap = this.checked; 255 269 updateGameAttributes(); 256 270 }; 257 271 272 Engine.GetGUIObjectByName("observerLateJoin").onPress = function() { 273 g_GameAttributes.settings.observerLateJoin = this.checked; 274 updateGameAttributes(); 275 }; 276 258 277 Engine.GetGUIObjectByName("disableTreasures").onPress = function() { 259 278 g_GameAttributes.settings.DisableTreasures = this.checked; 260 279 updateGameAttributes(); 261 280 }; 262 281 … … 314 333 } 315 334 else 316 335 { 317 336 Engine.GetGUIObjectByName("optionCheats").hidden = false; 318 337 Engine.GetGUIObjectByName("enableCheats").checked = false; 338 Engine.GetGUIObjectByName("optionObserverLateJoin").hidden = false; 319 339 g_GameAttributes.settings.CheatsEnabled = false; 320 340 // Setup ranked option if we are connected to the lobby. 321 341 if (Engine.HasXmppClient()) 322 342 { 323 343 Engine.GetGUIObjectByName("optionRating").hidden = false; … … 329 349 } 330 350 if (g_IsController) 331 351 { 332 352 Engine.GetGUIObjectByName("enableCheatsText").hidden = true; 333 353 Engine.GetGUIObjectByName("enableCheats").hidden = false; 354 Engine.GetGUIObjectByName("observerLateJoinText").hidden = true; 355 Engine.GetGUIObjectByName("observerLateJoin").hidden = false; 356 334 357 if (Engine.HasXmppClient()) 335 358 { 336 359 Engine.GetGUIObjectByName("enableRatingText").hidden = true; 337 360 Engine.GetGUIObjectByName("enableRating").hidden = false; 338 361 } … … 1186 1209 var enableCheats = Engine.GetGUIObjectByName("enableCheats"); 1187 1210 var enableRating = Engine.GetGUIObjectByName("enableRating"); 1188 1211 var populationCap = Engine.GetGUIObjectByName("populationCap"); 1189 1212 var startingResources = Engine.GetGUIObjectByName("startingResources"); 1190 1213 var ceasefire = Engine.GetGUIObjectByName("ceasefire"); 1214 var observerLateJoin = Engine.GetGUIObjectByName("observerLateJoin"); 1191 1215 1192 1216 var numPlayersText= Engine.GetGUIObjectByName("numPlayersText"); 1193 1217 var mapSizeDesc = Engine.GetGUIObjectByName("mapSizeDesc"); 1194 1218 var mapSizeText = Engine.GetGUIObjectByName("mapSizeText"); 1219 var observerLateJoinText = Engine.GetGUIObjectByName("observerLateJoinText"); 1195 1220 var revealMapText = Engine.GetGUIObjectByName("revealMapText"); 1196 1221 var exploreMapText = Engine.GetGUIObjectByName("exploreMapText"); 1197 1222 var disableTreasuresText = Engine.GetGUIObjectByName("disableTreasuresText"); 1198 1223 var victoryConditionText = Engine.GetGUIObjectByName("victoryConditionText"); 1199 1224 var lockTeamsText = Engine.GetGUIObjectByName("lockTeamsText"); … … 1220 1245 enableCheats.enabled = !enableRating.checked; 1221 1246 lockTeams.enabled = !enableRating.checked; 1222 1247 } 1223 1248 else 1224 1249 enableRatingText.caption = "Unknown"; 1250 1251 observerLateJoin.checked = g_GameAttributes.settings.observerLateJoin; 1252 observerLateJoinText.caption = (observerLateJoin.checked ? translate("Yes") : translate("No")); 1253 1225 1254 gameSpeedText.caption = g_GameSpeeds.names[speedIdx]; 1226 1255 gameSpeedBox.selected = speedIdx; 1227 1256 populationCap.selected = (mapSettings.PopulationCap !== undefined && POPULATION_CAP_DATA.indexOf(mapSettings.PopulationCap) != -1 ? POPULATION_CAP_DATA.indexOf(mapSettings.PopulationCap) : POPULATION_CAP_DEFAULTIDX); 1228 1257 populationCapText.caption = POPULATION_CAP[populationCap.selected]; 1229 1258 startingResources.selected = (mapSettings.StartingResources !== undefined && STARTING_RESOURCES_DATA.indexOf(mapSettings.StartingResources) != -1 ? STARTING_RESOURCES_DATA.indexOf(mapSettings.StartingResources) : STARTING_RESOURCES_DEFAULTIDX); -
binaries/data/mods/public/gui/gamesetup/gamesetup.xml
268 268 <!-- End Options --> 269 269 </object> 270 270 271 271 <!-- More Options --> 272 272 <object hidden="true" name="moreOptionsFade" type="image" z="60" sprite="ModernFade"/> 273 <object name="moreOptions" type="image" sprite="ModernDialog" size="50%-200 50%-195 50%+200 50%+2 20" z="70" hidden="true">273 <object name="moreOptions" type="image" sprite="ModernDialog" size="50%-200 50%-195 50%+200 50%+250" z="70" hidden="true"> 274 274 <object style="ModernLabelText" type="text" size="50%-128 -18 50%+128 14"> 275 275 <translatableAttribute id="caption">More Options</translatableAttribute> 276 276 </object> 277 277 278 278 <object size="14 38 94% 66"> … … 383 383 <object name="enableRating" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip"> 384 384 <translatableAttribute id="tooltip">Toggle if this game will be rated for the leaderboard.</translatableAttribute> 385 385 </object> 386 386 </object> 387 387 388 <object name="optionObserverLateJoin" size="14 368 94% 396" hidden="true"> 389 <object size="0 0 40% 28" type="text" hidden="false" style="ModernRightLabelText"> 390 <translatableAttribute id="caption" comment="Allow observers to join after the game started:">Observers can join after gamestart:</translatableAttribute> 391 </object> 392 <object name="observerLateJoinText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/> 393 <object name="observerLateJoin" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip"> 394 <translatableAttribute id="tooltip" comment="Allow observers to join after the game started:">Allow observers to join after the game started:</translatableAttribute> 395 </object> 396 </object> 397 388 398 <!-- Hide More Options Button --> 389 399 <object 390 400 name="hideMoreOptions" 391 401 type="button" 392 402 style="StoneButton" 393 size="50%-70 370 50%+70 396"403 size="50%-70 400 50%+70 426" 394 404 tooltip_style="onscreenToolTip" 395 405 hotkey="cancel" 396 406 > 397 407 <translatableAttribute id="caption">OK</translatableAttribute> 398 408 <translatableAttribute id="tooltip">Close more game options window</translatableAttribute> -
source/network/NetHost.h
60 60 enum NetDisconnectReason 61 61 { 62 62 NDR_UNKNOWN = 0, 63 63 NDR_UNEXPECTED_SHUTDOWN, 64 64 NDR_INCORRECT_PROTOCOL_VERSION, 65 NDR_SERVER_LOADING, 65 66 NDR_SERVER_ALREADY_IN_GAME 66 67 }; 67 68 68 69 class CNetHost 69 70 { -
source/network/NetMessages.h
26 26 #include "ps/CStr.h" 27 27 #include "scriptinterface/ScriptVal.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 0x0101000 6// Arbitrary protocol31 #define PS_PROTOCOL_VERSION 0x01010007 // 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. 35 35 // The message types having a negative value are used internally and not sent 36 36 // over the network. The message types used for network communication have -
source/network/NetServer.cpp
787 787 ENSURE(event->GetType() == (uint)NMT_AUTHENTICATE); 788 788 789 789 CNetServerSession* session = (CNetServerSession*)context; 790 790 CNetServerWorker& server = session->GetServer(); 791 791 792 CAuthenticateMessage* message = (CAuthenticateMessage*)event->GetParamRef(); 792 // Prohibit joins while the game is loading 793 if (server.m_State == SERVER_STATE_LOADING) 794 { 795 LOGMESSAGE("Refused connection while the game is loading"); 796 session->Disconnect(NDR_SERVER_LOADING); 797 return true; 798 } 793 799 800 CAuthenticateMessage* message = (CAuthenticateMessage*)event->GetParamRef(); 794 801 CStrW username = server.DeduplicatePlayerName(SanitisePlayerName(message->m_Name)); 795 796 802 bool isRejoining = false; 797 803 804 // If the game has started, only allow rejoins 798 805 if (server.m_State != SERVER_STATE_PREGAME) 799 806 { 800 // isRejoining = true; // uncomment this to test rejoining even if the player wasn't connected previously 807 // Optionally allow observers to join after the game has started 808 bool observerLateJoin; 809 JSContext* cx = server.GetScriptInterface().GetContext(); 810 JSAutoRequest rq(cx); 811 JS::RootedValue settings(cx); 812 server.GetScriptInterface().GetProperty(server.m_GameAttributes.get(), "settings", &settings); 813 server.GetScriptInterface().GetProperty(settings, "observerLateJoin", observerLateJoin); 801 814 802 815 // Search for an old disconnected player of the same name 803 816 // (TODO: if GUIDs were stable, we should use them instead) 804 for (PlayerAssignmentMap::iterator it = server.m_PlayerAssignments.begin(); it != server.m_PlayerAssignments.end(); ++it) 805 { 806 if (!it->second.m_Enabled && it->second.m_Name == username) 807 { 808 isRejoining = true; 809 break; 810 } 811 } 817 isRejoining = observerLateJoin || (std::find_if(server.m_PlayerAssignments.begin(), server.m_PlayerAssignments.end(), 818 [&username] (std::pair<CStr, PlayerAssignment> pair) { return pair.second.m_Enabled && pair.second.m_Name == username; }) != server.m_PlayerAssignments.end()); 812 819 813 820 // Players who weren't already in the game are not allowed to join now that it's started 814 821 if (!isRejoining) 815 822 { 816 823 LOGMESSAGE("Refused connection after game start from not-previously-known user \"%s\"", utf8_from_wstring(username));