GameStatePrimaryUserMonitor.inl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <GameState/GameStateRequestBus.h>
  9. #include <GameStateSamples/GameStateLevelLoading.h>
  10. #include <GameStateSamples/GameStateLevelPaused.h>
  11. #include <GameStateSamples/GameStateLevelRunning.h>
  12. #include <GameStateSamples/GameStatePrimaryControllerDisconnected.h>
  13. #include <GameStateSamples/GameStatePrimaryUserMonitor.h>
  14. #include <GameStateSamples/GameStatePrimaryUserSignedOut.h>
  15. #include <LocalUser/LocalUserRequestBus.h>
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////
  17. namespace GameStateSamples
  18. {
  19. ////////////////////////////////////////////////////////////////////////////////////////////////
  20. inline void GameStatePrimaryUserMonitor::OnPushed()
  21. {
  22. m_primaryControllerDisconnectedWhileLevelLoading = false;
  23. m_primaryUserSignedOutWhileLevelLoading = false;
  24. GameState::GameStateNotificationBus::Handler::BusConnect();
  25. AzFramework::InputDeviceNotificationBus::Handler::BusConnect();
  26. AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect();
  27. LocalUser::LocalUserNotificationBus::Handler::BusConnect();
  28. }
  29. ////////////////////////////////////////////////////////////////////////////////////////////////
  30. inline void GameStatePrimaryUserMonitor::OnPopped()
  31. {
  32. LocalUser::LocalUserNotificationBus::Handler::BusDisconnect();
  33. AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect();
  34. AzFramework::InputDeviceNotificationBus::Handler::BusDisconnect();
  35. GameState::GameStateNotificationBus::Handler::BusDisconnect();
  36. }
  37. ////////////////////////////////////////////////////////////////////////////////////////////////
  38. inline void GameStatePrimaryUserMonitor::OnActiveGameStateChanged(AZStd::shared_ptr<IGameState> oldGameState,
  39. [[maybe_unused]] AZStd::shared_ptr<IGameState> newGameState)
  40. {
  41. if (m_primaryUserSignedOutWhileLevelLoading &&
  42. azrtti_istypeof<GameStateLevelLoading>(oldGameState.get()))
  43. {
  44. // The primary user signed out while a level was loading,
  45. // we had to wait until the level finished loading before
  46. // transitioning to the primary user signed out game state.
  47. m_primaryUserSignedOutWhileLevelLoading = false;
  48. m_primaryControllerDisconnectedWhileLevelLoading = false;
  49. PushPrimaryUserSignedOutGameState();
  50. return;
  51. }
  52. if (m_primaryControllerDisconnectedWhileLevelLoading &&
  53. azrtti_istypeof<GameStateLevelLoading>(oldGameState.get()))
  54. {
  55. // The controller disconnected while a level was loading,
  56. // we had to wait until the level finished loading before
  57. // transitioning to the controller disconnected game state.
  58. m_primaryControllerDisconnectedWhileLevelLoading = false;
  59. PushPrimaryControllerDisconnectedGameState();
  60. return;
  61. }
  62. }
  63. ////////////////////////////////////////////////////////////////////////////////////////////////
  64. inline void GameStatePrimaryUserMonitor::OnInputDeviceConnectedEvent(const AzFramework::InputDevice& inputDevice)
  65. {
  66. const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
  67. if (m_primaryControllerDisconnectedWhileLevelLoading &&
  68. primaryLocalUserId == inputDevice.GetAssignedLocalUserId())
  69. {
  70. // The controller disconnected while a level was loading,
  71. // but was reconnected before the level finished loading.
  72. m_primaryControllerDisconnectedWhileLevelLoading = false;
  73. }
  74. }
  75. ////////////////////////////////////////////////////////////////////////////////////////////////
  76. inline void GameStatePrimaryUserMonitor::OnInputDeviceDisconnectedEvent(const AzFramework::InputDevice& inputDevice)
  77. {
  78. const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
  79. if (primaryLocalUserId != inputDevice.GetAssignedLocalUserId() ||
  80. primaryLocalUserId == AzFramework::LocalUserIdNone)
  81. {
  82. // The disconnected controller does not belong to the primary user,
  83. // or the primary user has not yet been set.
  84. return;
  85. }
  86. if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStateLevelLoading>())
  87. {
  88. // The controller disconnected while a level is loading;
  89. // we have to wait until the level has finished loading.
  90. m_primaryControllerDisconnectedWhileLevelLoading = true;
  91. return;
  92. }
  93. PushPrimaryControllerDisconnectedGameState();
  94. }
  95. ////////////////////////////////////////////////////////////////////////////////////////////////
  96. inline void GameStatePrimaryUserMonitor::OnApplicationUnconstrained(AzFramework::ApplicationLifecycleEvents::Event /*lastEvent*/)
  97. {
  98. const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
  99. if (primaryLocalUserId == AzFramework::LocalUserIdNone)
  100. {
  101. // The primary user has yet to be set
  102. m_primaryUserSignedOutWhileLevelLoading = false;
  103. return;
  104. }
  105. bool isPrimaryLocalUserSignedIn = false;
  106. LocalUser::LocalUserRequestBus::BroadcastResult(isPrimaryLocalUserSignedIn,
  107. &LocalUser::LocalUserRequests::IsLocalUserSignedIn,
  108. primaryLocalUserId);
  109. if (isPrimaryLocalUserSignedIn)
  110. {
  111. // The primary user is still signed in
  112. m_primaryUserSignedOutWhileLevelLoading = false;
  113. return;
  114. }
  115. if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStateLevelLoading>())
  116. {
  117. // The primary user signed out while a level is loading;
  118. // we have to wait until the level has finished loading.
  119. m_primaryUserSignedOutWhileLevelLoading = true;
  120. return;
  121. }
  122. PushPrimaryUserSignedOutGameState();
  123. }
  124. ////////////////////////////////////////////////////////////////////////////////////////////////
  125. inline void GameStatePrimaryUserMonitor::OnLocalUserSignedIn(AzFramework::LocalUserId localUserId)
  126. {
  127. const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
  128. if (m_primaryUserSignedOutWhileLevelLoading &&
  129. primaryLocalUserId == localUserId)
  130. {
  131. // The primary user signed out while a level was loading,
  132. // but signed in again before the level finished loading.
  133. m_primaryUserSignedOutWhileLevelLoading = false;
  134. }
  135. }
  136. ////////////////////////////////////////////////////////////////////////////////////////////////
  137. inline void GameStatePrimaryUserMonitor::OnLocalUserSignedOut(AzFramework::LocalUserId localUserId)
  138. {
  139. const AzFramework::LocalUserId primaryLocalUserId = LocalUser::LocalUserRequests::GetPrimaryLocalUserId();
  140. if (primaryLocalUserId != localUserId ||
  141. primaryLocalUserId == AzFramework::LocalUserIdNone)
  142. {
  143. // The user that signed out is not the primary user,
  144. // or the primary user has not yet been set.
  145. return;
  146. }
  147. if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStateLevelLoading>())
  148. {
  149. // The primary user signed out while a level is loading;
  150. // we have to wait until the level has finished loading.
  151. m_primaryUserSignedOutWhileLevelLoading = true;
  152. return;
  153. }
  154. PushPrimaryUserSignedOutGameState();
  155. }
  156. ////////////////////////////////////////////////////////////////////////////////////////////////
  157. inline void GameStatePrimaryUserMonitor::PushPrimaryControllerDisconnectedGameState()
  158. {
  159. if (GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStatePrimaryControllerDisconnected>() ||
  160. GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStatePrimaryUserSignedOut>())
  161. {
  162. // The controller disconnection has already been detected,
  163. // or the primary user signed out (which takes precedence).
  164. return;
  165. }
  166. // Ensure the game is paused if needed before pushing the controller disconnected game state
  167. TryPushLevelPausedGameState();
  168. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<GameStatePrimaryControllerDisconnected>();
  169. }
  170. ////////////////////////////////////////////////////////////////////////////////////////////////
  171. inline void GameStatePrimaryUserMonitor::PushPrimaryUserSignedOutGameState()
  172. {
  173. if (GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStatePrimaryUserSignedOut>())
  174. {
  175. // The primary user sign out has already been detected
  176. return;
  177. }
  178. if (GameState::GameStateRequests::IsActiveGameStateOfType<GameStatePrimaryControllerDisconnected>())
  179. {
  180. // The primary user signing out takes precedence over their controller being disconnected
  181. GameState::GameStateRequestBus::Broadcast(&GameState::GameStateRequests::PopActiveGameState);
  182. }
  183. // Ensure the game is paused if needed before pushing the primary user signed out game state
  184. TryPushLevelPausedGameState();
  185. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<GameStatePrimaryUserSignedOut>();
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////////////////////
  188. inline void GameStatePrimaryUserMonitor::TryPushLevelPausedGameState()
  189. {
  190. if (GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStateLevelPaused>() ||
  191. !GameState::GameStateRequests::DoesStackContainGameStateOfType<GameStateLevelRunning>())
  192. {
  193. // The game has already been paused or is not actively running yet
  194. return;
  195. }
  196. GameState::GameStateRequests::CreateAndPushNewOverridableGameStateOfType<GameStateLevelPaused>();
  197. }
  198. }